Decompress byte array to string via BinaryReader yields empty string - c#

I am trying to decompress a byte array and get it into a string using a binary reader. When the following code executes, the inStream position changes from 0 to the length of the array, but str is always an empty string.
BinaryReader br = null;
string str = String.Empty;
using (MemoryStream inStream = new MemoryStream(pByteArray))
{
GZipStream zipStream = new GZipStream(inStream, CompressionMode.Decompress);
BinaryReader br = new BinaryReader(zipStream);
str = br.ReadString();
inStream.Close();
br.Close();
}

You haven't shown how is the data being compressed, but here's a full example of compressing and decompressing a buffer:
using System;
using System.IO;
using System.IO.Compression;
using System.Text;
class Program
{
static void Main()
{
var test = "foo bar baz";
var compressed = Compress(Encoding.UTF8.GetBytes(test));
var decompressed = Decompress(compressed);
Console.WriteLine(Encoding.UTF8.GetString(decompressed));
}
static byte[] Compress(byte[] data)
{
using (var compressedStream = new MemoryStream())
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
{
zipStream.Write(data, 0, data.Length);
zipStream.Close();
return compressedStream.ToArray();
}
}
static byte[] Decompress(byte[] data)
{
using (var compressedStream = new MemoryStream(data))
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
}
}

Related

How to convert from a gzip compressed file to Zstandard

How do I convert from a gzip compressed file to Zstandard? Here is my attempt:
using Zstandard.Net;
public static void ConvertToZstd(string path)
{
byte[] compressed = null;
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (var memoryStream = new MemoryStream())
using (var compressionStream = new ZstandardStream(memoryStream, CompressionMode.Compress))
{
compressionStream.CompressionLevel = 11; // optional!!
//compressionStream.CompressionDictionary = dictionary; // optional!!
compressionStream.Write(gzipStream, 0, gzipStream.Length);
compressionStream.Close();
compressed = memoryStream.ToArray();
}
}
public static void ConvertToZstd(string path, string outputPath)
{
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (var memoryStream = new MemoryStream())
using (var compressionStream = new ZstandardStream(memoryStream, CompressionMode.Compress))
{
compressionStream.CompressionLevel = 11; // optional!!
//compressionStream.CompressionDictionary = dictionary; // optional!!
gzipStream.CopyTo(compressionStream);
compressionStream.Close();
File.WriteAllBytes(outputPath, memoryStream.ToArray());
}
}

C# Cannot access a closed stream while copying GZipStream to MemoryStream

I've been trying to convert a GZipStream into a MemoryStream and then convert it to a byte array without having to write any files to the hard drive. I've been trying to copy it to a MemoryStream but I've been getting this error: Unhandled Exception: System.ObjectDisposedException: Cannot access a closed Stream.
I've looked at some of the other solutions, but I haven't been able to successfully implement them into what I'm trying to accomplish.
GZipStream decompressedStream = Decompress(new FileInfo(args[0]));
using (var finalStream = new MemoryStream())
{
decompressedStream.CopyTo(finalStream);
byte[] decompressedBytes = new byte[finalStream.Length];
}
EDIT: Somebody wanted me to add the code for Decompress() so here it is
public static GZipStream Decompress(FileInfo fileToDecompress)
{
using (FileStream originalFileStream = fileToDecompress.OpenRead())
{
string currentFileName = fileToDecompress.FullName;
string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length) + " (decompressed)";
using (FileStream decompressedFileStream = File.Create(newFileName))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
return decompressionStream;
}
}
}
}
The issue is here:
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
return decompressionStream;
}
using statement (see this article) disposes the stream and you can't use it outside of the block. Move your MemoryStream handling inside this block and return byte[] from the method.
Something like this should work:
public static byte[] Decompress(FileInfo fileToDecompress)
{
using (FileStream originalFileStream = fileToDecompress.OpenRead())
{
string currentFileName = fileToDecompress.FullName;
string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length) + " (decompressed)";
using (FileStream decompressedFileStream = File.Create(newFileName))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
using (var finalStream = new MemoryStream())
{
decompressionStream.CopyTo(finalStream);
return finalStream.ToArray();
}
}
}
}

How do I use System.Io.Compression to replace GzipDotNet.dll

I am working on an existing system where data is stored in a compressed byte array in a database.
The existing data has all been compressed using GZipDotNet.dll.
I am trying to switch to using the gzip functions in System.IO.Compression.
When I use:
public static byte[] DeCompressByteArray(byte[] inArray)
{
byte[] outStream = null;
outStream = GZipDotNet.GZip.Uncompress(inArray);
return outStream;
}
It works fine but:
public static byte[] DeCompressByteArray(byte[] inArray)
{
byte[] outStream = null;
using (var compressedStream = new MemoryStream(inArray))
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
outStream = resultStream.ToArray();
}
return outStream;
}
Gives a response of:
The magic number in GZip header is not correct. Make sure you are passing in a GZip stream

compression and utf8 encoding

can someone tell me why I'm loosing information doing this process ? Some utf8 chars appears not decoded :
"Biography":"\u003clink type=... or Steve Blunt \u0026 Marty Kelley
but others do : "Name":"朱敬
// Creating a 64bit string containing gzip data
string bar;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress))
using (StreamWriter writer = new StreamWriter(gzip, System.Text.Encoding.UTF8))
{
writer.Write(s);
}
ms.Flush();
bar = Convert.ToBase64String(ms.ToArray());
}
// Reading it
string foo;
byte[] itemData = Convert.FromBase64String(bar);
using (MemoryStream src = new MemoryStream(itemData))
using (GZipStream gzs = new GZipStream(src, CompressionMode.Decompress))
using (MemoryStream dest = new MemoryStream(itemData.Length*2))
{
gzs.CopyTo(dest);
foo = Encoding.UTF8.GetString(dest.ToArray());
}
Console.WriteLine(foo);
It could be because you are writing the string using StreamWriter but reading it using CopyTo() and Encoding.GetString().
What happens if you try this?
// Reading it
string foo;
byte[] itemData = Convert.FromBase64String(bar);
using (MemoryStream src = new MemoryStream(itemData))
using (GZipStream gzs = new GZipStream(src, CompressionMode.Decompress))
using (StreamReader reader = new StreamReader(gzs, Encoding.UTF8))
{
foo = reader.ReadLine();
}
Although I think you should be using BinaryReader and BinaryWriter:
string s = "Biography:\u003clink type...";
string bar;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress))
using (var writer = new BinaryWriter(gzip, Encoding.UTF8))
{
writer.Write(s);
}
ms.Flush();
bar = Convert.ToBase64String(ms.ToArray());
}
// Reading it
string foo;
byte[] itemData = Convert.FromBase64String(bar);
using (MemoryStream src = new MemoryStream(itemData))
using (GZipStream gzs = new GZipStream(src, CompressionMode.Decompress))
using (var reader = new BinaryReader(gzs, Encoding.UTF8))
{
foo = reader.ReadString();
}
Console.WriteLine(foo);
The issue was simply that the characters were already encoded in the source string.
Ps : Credit goes to rik for this answer :)
Edit : I also had the StreamReader issue matthew-watson was suggesting.

GZipStream.Write Method

I have been reading for a short while about GZipStream and its Write method. What I am attempting to do is convert the compressed data from the stream and put it in a byte array. I will leave you with my code below as I believe it will help significantly.
public static void Compress(byte[] fi)
{
using (MemoryStream inFile = new MemoryStream(fi))
using (FileStream outFile = File.Create(#"C:\Compressed.exe"))
using (GZipStream Compress = new GZipStream(outFile, CompressionMode.Compress))
{
inFile.CopyTo(Compress);
}
}
Rather than writing to a file on my disk, I would like to write the compressed data onto a byte array, and then return the byte array (assuming I made this a function of course).
You can simply use use another MemoryStream and its ToArray method.
public static byte[] Compress(byte[] fi)
{
using (MemoryStream outFile = new MemoryStream())
{
using (MemoryStream inFile = new MemoryStream(fi))
using (GZipStream Compress = new GZipStream(outFile, CompressionMode.Compress))
{
inFile.CopyTo(Compress);
}
return outFile.ToArray();
}
}
From one of my extension libraries
public static string Compress(this string s)
{
byte[] bytesToEncode = Encoding.UTF8.GetBytes(s);
return Convert.ToBase64String(bytesToEncode.Compress());
}
public static byte[] Compress(this byte[] bytesToEncode)
{
using (MemoryStream input = new MemoryStream(bytesToEncode))
using (MemoryStream output = new MemoryStream())
{
using (System.IO.Compression.GZipStream zip = new System.IO.Compression.GZipStream(output, System.IO.Compression.CompressionMode.Compress))
{
input.CopyTo(zip);
}
return output.ToArray();
}
}
public static string Explode(this string s)
{
byte[] compressedBytes = Convert.FromBase64String(s);
return Encoding.UTF8.GetString(compressedBytes.Explode());
}
public static byte[] Explode(this byte[] compressedBytes)
{
using (MemoryStream input = new MemoryStream(compressedBytes))
using (MemoryStream output = new MemoryStream())
{
using (System.IO.Compression.GZipStream zip = new System.IO.Compression.GZipStream(input, System.IO.Compression.CompressionMode.Decompress))
{
zip.CopyTo(output);
}
return output.ToArray();
}
}

Categories

Resources