GZipStream Compression

I am trying to understand why my code is not executing at will. It creates a GZipStream and then saves the object as a compressed file on my hard drive, but the saved file is always 0 bytes.

Now I know how to save the file using GZipStream , but my question is not how to do it. My question is why this code stores 0 bytes (or why FileStream works and memory doesn't work).

private void BegingCompression() { var bytes = File.ReadAllBytes(this.fileName); using (MemoryStream ms = new MemoryStream(bytes)) { ms.ReadByte(); using (FileStream fs =new FileStream(this.newFileName, FileMode.CreateNew)) using (GZipStream zipStream = new GZipStream(ms, CompressionMode.Compress, false)) { zipStream.Write(bytes, 0, bytes.Length); } } } 

As for the source code, this.fileName = c:\Audio.wav and newFileName are c:\Audio.wav.gz (but also tried c:\audio.gz )

+7
source share
3 answers
  • You do not need a MemoryStream, because bytes already has data to compress.
  • ms.ReadByte() should not be used.
  • When creating a zipStream , you should use the output file stream.

Try the following:

 var bytes = File.ReadAllBytes(this.fileName); using (FileStream fs =new FileStream(this.newFileName, FileMode.CreateNew)) using (GZipStream zipStream = new GZipStream(fs, CompressionMode.Compress, false)) { zipStream.Write(bytes, 0, bytes.Length); } 

EDIT

The source code creates a file with zero length because you are not writing to the file stream.

+9
source

When you use GzipStream or DeflateStream from the System.IO.Compression namespace, the Stream that you specify in the constructor will be written to for compression and read in decompression .

Since you are trying to compress data here, using a MemoryStream is wrong, because you are not trying to compress it, but rather use it as a data source. So your MemoryStream should be Stream input, and FileStream should be your output.

I highly recommend using a MemoryStream as a data source over raw byte[] , because Stream has much more versatility and application ( FileStream , NetworkStream , CryptoStream , etc.)

Here are some examples using the async / await pattern:

 public static async Task CompressToFileAsync(byte[] buffer, string outputFile) { using (var inputStream = new MemoryStream(buffer)) await CompressToFileAsync(inputStream, outputFile); } public static async Task CompressToFileAsync(Stream inputStream, string outputFile) { using (var outputStream = File.Create(outputFile)) using (var gzip = new GZipStream(outputStream, CompressionMode.Compress)) { await inputStream.CopyToAsync(gzip); gzip.Close(); } } public static async Task<MemoryStream> DecompressFromFileAsync(string inputFile) { var outputStream = new MemoryStream(); using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var gzip = new GZipStream(inputStream, CompressionMode.Decompress)) { await gzip.CopyToAsync(outputStream); gzip.Close(); inputStream.Close(); // After writing to the MemoryStream, the position will be the size // of the decompressed file, we should reset it back to zero before returning. outputStream.Position = 0; return outputStream; } } 

NOTE. Always call GzipStream.Close() before closing the Stream input or output. It does some final flushing of the buffer on close / delete, and if the input or output is closed, it throws an exception when it tries to do this. (This also applies to DeflateStream )

+7
source
 why FileStream works and memory doesn't 

Since the memory store, MemoryStream is your RAM, not your hard drive. Therefore, when you pass a MemoryStream object to the GZipStream constructor, you gzip will only be in RAM.

With this code:

 using (FileStream fs =new FileStream(this.newFileName, FileMode.CreateNew)) 

You are creating a new FileStream, but you have not used it. To save gzip with this FIleStream, you need to pass it to the GZipStream constructor to make it backup storage for your hard drive.

+2
source

All Articles