How can I get rid of the CA2202 warning (CA2202 : Microsoft.Usage : Object 'compressedStream' can be disposed more than once in method 'Compression.InternalDecompress(byte[])'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object) from the following code:
using (var compressedStream = new MemoryStream(inputData))
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
I have tried getting rid of the "using" statement and replacing it with try/finally pattern but then I get CA2000 (CA2000 : Microsoft.Reliability : In method 'Compression.InternalDecompress(byte[])', call System.IDisposable.Dispose on object 'stream' before all references to it are out of scope). I have tried replacing the above code like this:
MemoryStream decompressedData = null;
MemoryStream stream = null;
GZipStream decompressor = null;
try
{
decompressedData = new MemoryStream();
stream = new MemoryStream(inputData);
decompressor = new GZipStream(stream, CompressionMode.Decompress, false);
stream = null;
int bytesRead = 1;
int chunkSize = 4096;
byte[] chunk = new byte[chunkSize];
while ((bytesRead = decompressor.Read(chunk, 0, chunkSize)) > 0)
{
decompressedData.Write(chunk, 0, bytesRead);
}
decompressor = null;
return decompressedData.ToArray();
}
finally
{
if (stream != null)
{
stream.Dispose();
}
if (decompressor != null)
{
decompressor.Dispose();
}
if (decompressedData != null)
{
decompressedData.Dispose();
}
}
This is what i use:
public class Compression
{
public Compression()
{
}
public byte[] Compress(byte[] buffer)
{
byte[] gzBuffer;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
{
zip.Write(buffer, 0, buffer.Length);
zip.Close();
}
ms.Position = 0;
MemoryStream outStream = new MemoryStream();
byte[] compressed = new byte[ms.Length];
ms.Read(compressed, 0, compressed.Length);
gzBuffer = new byte[compressed.Length + 4];
Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
}
return gzBuffer;
}
public byte[] Decompress(byte[] gzBuffer)
{
byte[] buffer;
using (MemoryStream ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
buffer = new byte[msgLength];
ms.Position = 0;
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
zip.Read(buffer, 0, buffer.Length);
}
}
return buffer;
}
}
Or you can just add a pragma statement to your class
#pragma warning disable 2202
namespace Your.Namespace
{
...
}
#pragma warning restore 2202
This is what I ended up using - gets rid of both CA2000 and CA2202:
private static MemoryStream GetMemoryStream()
{
return new MemoryStream();
}
private static byte[] InternalDecompress(byte[] inputData)
{
Debug.Assert(inputData != null, "inputData cannot be null");
MemoryStream decompressedData = GetMemoryStream();
MemoryStream inputDataMemoryStream = GetMemoryStream();
GZipStream decompressor = null;
try
{
inputDataMemoryStream.Write(inputData, 0, inputData.Length);
inputDataMemoryStream.Position = 0;
decompressor = new GZipStream(inputDataMemoryStream, CompressionMode.Decompress, false);
int bytesRead;
int chunkSize = 4096;
byte[] chunk = new byte[chunkSize];
while ((bytesRead = decompressor.Read(chunk, 0, chunkSize)) > 0)
{
decompressedData.Write(chunk, 0, bytesRead);
}
}
finally
{
if (decompressor != null)
{
decompressor.Dispose();
}
}
return decompressedData.ToArray();
}
This is my attempt. It works and it avoids CA2202
/// <summary>
/// Compresses byte array to new byte array.
/// </summary>
public byte[] Compress(byte[] raw)
{
MemoryStream outStream = null;
GZipStream tinyStream = null;
byte[] retValue = null;
try
{
outStream = new MemoryStream();
tinyStream = new GZipStream(outStream, CompressionMode.Compress);
using (var mStream = new MemoryStream(raw))
mStream.CopyTo(tinyStream);
}
finally
{
if (tinyStream != null)
{
tinyStream.Dispose();
retValue = outStream.ToArray();
}
else if (outStream != null)
{
retValue = outStream.ToArray();
outStream.Dispose();
}
}
return retValue;
}
Related
When I am trying to deflate one string to XML getting the error. can anyone help me out, if the string is wrong or any other thing I need to consider?
string output = DecompressString("H4sIAAAAAAAAAO1ay3LbIBTd9ys83hOcZrrxKP6CZpUuusUStulIoAFkxfn6XpCQ0NvWTDt+ZBUJ7vtwEQcneHv7ReN3Ko8spGrxkcRcrT8Ue10etE7XGOd5/pS/PAm5x99Xq2f8++3ne3igCUGMK014SJeFVqWRSfZEtWJWh+85TokkicIghRVLFPiCl5Cky823xSIIRZLGVFMkJNszTjTje8QiyjXTJ5RKquARRgU34qAwKbcgoWZH+rrUMqNL7NRSKokWctrPgmT6AFKfNCptFCbACEhpyUIjhcSRSgkGNu4BcaFR4TvAvZLOTEjimEoUMZXG5IQ4SaiLYGMcBnhMosgHn5+QrTO+rNATuHjpnQuLr1NBtCOxmoNR05iHV2GwqnQioOxgNSEcVANs33vQ3EC9wQE7EsiY8Z0ADTPeAPLyyrfrNIVCW7yShock4ywsrEZQO6nqiAZmm41Qp53FEKF2bZtJvmZU79ZFn65heA2bgLEJxlIRs/BUKZfqCwalNmsUQaVyIiOTRcZDwSNmYiAx2p7QEfISnqqNtJRQ/rABikaMzN9JrCuA11hpWTbxoojaWgC60WwnuJEJ7k8lIBY95QnDGoIQZlWQZBH7TxW0rm6+gttMne596YFhk+YNoHDPy/f6UeACvidp/Aj9AKkSrnIqbwSOO2+MW4ADzjYZOLSHdgk1OJAtVOMRWsXL9xbxufveuR58ijfgCo75jNOQihcN8pFhotZUkcB5eMGdOdCxoyjGN2FMSdt8QwKJXe2vHe+Q1ZoPuvn8QMu4LT+T9A8NAWREdDkKz1rYBbqB2oJQRs0AAdKuPUUjYCjkHLsuKi00kAGeJVvoBj89ZdoFmaXSrMjmeRXgy7UqJEAUqhO5qmmWQDQvYLN/ph/BZidX375CZdVGZlTaD4zD2XK3g5RqQ93RNk0fWbUeIR+TGhDKCTM49rLwcm7qpmNAafAGymyTbmVBlUIKxpXZJNnOGTkwhexuCn9dhNZ7ca00Q3u8oJ7UYDl9mQGRg4ij8eoYiW5p8KhjZ3XI65ZIWafIgIAnpkC9Qv/4PqX0YrrV1r+KBd7UvZ9Mpr5RrSCgJCKfn17ZDtZKM4qOu+ETyyRe93xSuRG8OieY8Q53+0+m9+JKtoE6lq9t4GqW1UV4fW0DV4UX45pKTh7jZwp7pvHy/UL9EX5aeWjUO5/88a95m3JMUYBe+uEbmDo8XMZfvChrCpNQpcieOlblcfJ2MMOS04GMe/EJFQfuTXlIu/TNzYww2oR8eIIIVoRmIUsJ1/YiY2S6S0v9QBolbUxU43Y7Hom/PT8vix8XJdEXk5dK73SdaKY0rN5Pc6UUl5dMWvAuMANyPTd0neU54sILpLxoODugCflzApt0GeDGfzttvv0F8ylWAP4kAAA=");
public static string DecompressString(string compressedString)
{
byte[] decompressedBytes;
var compressedStream = new MemoryStream(Convert.FromBase64String(compressedString));
using (var decompressorStream = new DeflateStream(compressedStream, CompressionMode.Decompress))
{
using (var decompressedStream = new MemoryStream())
{
decompressorStream.CopyTo(decompressedStream);
decompressedBytes = decompressedStream.ToArray();
}
}
return Encoding.UTF8.GetString(decompressedBytes);
}
public static string DecodeGzip(string str)
{
byte[] gzBuffer = Convert.FromBase64String(str);
using (MemoryStream ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 0, gzBuffer.Length);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
int length;
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
length = zip.Read(buffer, 0, buffer.Length);
}
var data = new byte[length];
Array.Copy(buffer, data, length);
return Encoding.UTF8.GetString(data);
}
}
I was using GZipStream for some time without any problems. I didn't change any code at my function but now the compress and decompress doesn't work. I have extracted the following simple example (maybe I do something wrong generally...).
public static class ZipLib
{
#region Public Methods
public static string Unzip(byte[] compressedText)
{
try {
byte[] gzBuffer = compressedText;
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
byte[] buffer = new byte[msgLength];
using (MemoryStream ms = new MemoryStream()) {
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress, true)) {
zip.Read(buffer, 0, buffer.Length);
}
}
return Encoding.UTF8.GetString(buffer);
}
catch (Exception ex) {
Debug.WriteLine(ex.Message);
}
return "";
}
public static byte[] Zip(string text)
{
byte[] buffer = Encoding.UTF8.GetBytes(text);
MemoryStream ms = new MemoryStream();
using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true)) {
zip.Write(buffer, 0, buffer.Length);
}
ms.Position = 0;
byte[] compressed = new byte[ms.Length];
ms.Read(compressed, 0, compressed.Length);
byte[] gzBuffer = new byte[compressed.Length + 4];
Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
return gzBuffer;
}
#endregion
}
internal class Program
{
#region Private Methods
private static void Main(string[] args)
{
string uncompressedIn = "Hallo Welt";
var compressed = ZipLib.Zip(uncompressedIn);
var uncompressed = ZipLib.Unzip(compressed);
Console.WriteLine("Uncompressed Input: " + uncompressedIn);
Console.WriteLine("Compressed value: " + string.Join(" | ", compressed));
Console.WriteLine("Uncompressed from compressed: " + string.Join(" | ", uncompressed.ToCharArray()));
Console.ReadKey();
}
#endregion
}
The value of uncompressed is "\0\0\0\0"...
In Unzip, you Write to a MemoryStream, then give it to the GZipStream to read from, but: it is still at the end of the stream, you didn't rewind it. Try adding:
ms.Position = 0;
after the Write. Note, however, that it might be more efficient to do:
using(MemoryStream ms = new MemoryStream(gzBuffer, 4, gzBuffer.Length - 4))
{
//...
}
this avoids duplicating any memory
I read compressed data one block at a time and add these blocks to the queue. Then when I try to decompress that data using GzipStream InvalidDataException is shown stating that the magic number in the GzipHeader is incorrect. What header should my blocks have?
Here's my decompression code:
private DataBlock Decompress(DataBlock sourceBlock)
{
var decompressed = new byte[sourceBlock.Data.Length];
using (MemoryStream memory = new MemoryStream(sourceBlock.Data))
{
using (GZipStream gzip = new GZipStream(memory, CompressionMode.Decompress))
{
gzip.Read(decompressed, 0, sourceBlock.Data.Length);
}
return new DataBlock(decompressed, sourceBlock.Id);
}
}
Here's my compression code:
private DataBlock Compress(DataBlock sourceBlock)
{
using (MemoryStream memory = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(memory, CompressionMode.Compress))
{
gzip.Write(sourceBlock.Data, 0, sourceBlock.Data.Length);
}
return new DataBlock(memory.ToArray(), sourceBlock.Id);
}
}
Read blocks from file:
private void ReadDataFromFile()
{
if (File.Exists(this.sourceFilePath))
{
try
{
using (var fsSource = new FileStream(this.sourceFilePath, FileMode.Open, FileAccess.Read))
{
while (fsSource.CanRead)
{
var buffer = new byte[this.bufferLength];
int n = fsSource.Read(buffer, 0, buffer.Length);
if (n == 0)
{
break;
}
var block = new DataBlock(buffer, this.currentReadBlockNumber++);
lock (this.innerDataBlockQueue)
{
innerDataBlockQueue.Enqueue(block);
}
this.newBlockDataLoaded?.Invoke(this, EventArgs.Empty);
SpinWait.SpinUntil(() => this.QueueIsFull(this.innerDataBlockQueue) == false);
}
}
}
catch (Exception e)
{
throw e;
}
}
}
if (File.Exists(copypath)) File.Delete(copypath);
using (FileStream inputstream = new FileStream(plainpath, FileMode.Open))
{
using (FileStream outputstream = new FileStream(copypath, FileMode.CreateNew))
{
Object lock1 = new Object();
long inputlength = inputstream.Length;
Parallel.For((long)0, (long)(inputlength / bufferSize) + ((inputlength%bufferSize)>0?1:0), (i) =>
{
byte[] parallelbuff = new byte[bufferSize];
long cursor = -1;
lock (lock1)
{
cursor = (long)(i * bufferSize);
inputstream.Seek(cursor, SeekOrigin.Begin);
read = inputstream.Read(parallelbuff, 0, buff.Length);
}
if (read > 0)
{
lock (lock1)
{
outputstream.Seek(cursor, SeekOrigin.Begin);
outputstream.Write(parallelbuff, 0, read);
}
}
});
}
}
This is a piece of my .NET 4.5 C# code for copying file from 'plainpath' to 'copypath'.
But it doesn't copy some parts of the original file.
Can you tell me about my mistake in it?
I have several .gz files, and I want to decompress them one by one.
I have writen a simple code using GzipStream in C#, but got failed. I wonder a correct and useful method to achieve what I want. Thanks a lot.
private string Extrgz(string infile)
{
string dir = Path.GetDirectoryName(infile);
string decompressionFileName = dir + Path.GetFileNameWithoutExtension(infile) + "_decompression.bin";
using (GZipStream instream = new GZipStream(File.OpenRead(infile), CompressionMode.Compress))// ArgumentException...
{
using (FileStream outputStream = new FileStream(decompressionFileName, FileMode.Append, FileAccess.Write))
{
int bufferSize = 8192, bytesRead = 0;
byte[] buffer = new byte[bufferSize];
while ((bytesRead = instream.Read(buffer, 0, bufferSize)) > 0)
{
outputStream.Write(buffer, 0, bytesRead);
}
}
}
return decompressionFileName;
}
You need to decompress but you set CompressionMode.Compress, replace it with CompressionMode.Decompress.
Example here.
Here:
public static void DeCompressFile(string CompressedFile, string DeCompressedFile)
{
byte[] buffer = new byte[1024 * 1024];
using (System.IO.FileStream fstrmCompressedFile = System.IO.File.OpenRead(CompressedFile)) // fi.OpenRead())
{
using (System.IO.FileStream fstrmDecompressedFile = System.IO.File.Create(DeCompressedFile))
{
using (System.IO.Compression.GZipStream strmUncompress = new System.IO.Compression.GZipStream(fstrmCompressedFile,
System.IO.Compression.CompressionMode.Decompress))
{
int numRead = strmUncompress.Read(buffer, 0, buffer.Length);
while (numRead != 0)
{
fstrmDecompressedFile.Write(buffer, 0, numRead);
fstrmDecompressedFile.Flush();
numRead = strmUncompress.Read(buffer, 0, buffer.Length);
} // Whend
//int numRead = 0;
//while ((numRead = strmUncompress.Read(buffer, 0, buffer.Length)) != 0)
//{
// fstrmDecompressedFile.Write(buffer, 0, numRead);
// fstrmDecompressedFile.Flush();
//} // Whend
strmUncompress.Close();
} // End Using System.IO.Compression.GZipStream strmUncompress
fstrmDecompressedFile.Flush();
fstrmDecompressedFile.Close();
} // End Using System.IO.FileStream fstrmCompressedFile
fstrmCompressedFile.Close();
} // End Using System.IO.FileStream fstrmCompressedFile
} // End Sub DeCompressFile
// http://www.dotnetperls.com/decompress
public static byte[] Decompress(byte[] gzip)
{
byte[] baRetVal = null;
using (System.IO.MemoryStream ByteStream = new System.IO.MemoryStream(gzip))
{
// Create a GZIP stream with decompression mode.
// ... Then create a buffer and write into while reading from the GZIP stream.
using (System.IO.Compression.GZipStream stream = new System.IO.Compression.GZipStream(ByteStream
, System.IO.Compression.CompressionMode.Decompress))
{
const int size = 4096;
byte[] buffer = new byte[size];
using (System.IO.MemoryStream memory = new System.IO.MemoryStream())
{
int count = 0;
count = stream.Read(buffer, 0, size);
while (count > 0)
{
memory.Write(buffer, 0, count);
memory.Flush();
count = stream.Read(buffer, 0, size);
}
baRetVal = memory.ToArray();
memory.Close();
}
stream.Close();
} // End Using System.IO.Compression.GZipStream stream
ByteStream.Close();
} // End Using System.IO.MemoryStream ByteStream
return baRetVal;
} // End Sub Decompress