D.J
D.J

Reputation: 2534

Gzip uncompress from string error, The magic number in GZip header is not correct

I am trying to replicate the php function gzuncompress in C# So far I got part of following code working. see comment and code below.

I thing the tricky bit is happening during byte[] and string convertion. How can I fix this? and where did I missed??

I am using .Net 3.5 environment

        var plaintext = Console.ReadLine();
        Console.WriteLine("string to byte[] then to string");
        byte[] buff = Encoding.UTF8.GetBytes(plaintext);

        var compress = GZip.GZipCompress(buff);
        //Uncompress working below
        try
        {
            var unpressFromByte = GZip.GZipUncompress(compress);
            Console.WriteLine("uncompress successful by uncompress byte[]");
        }catch
        {
            Console.WriteLine("uncompress failed by uncompress byte[]");
        }

        var compressString = Encoding.UTF8.GetString(compress);
        Console.WriteLine(compressString);
        var compressBuff = Encoding.UTF8.GetBytes(compressString);
        Console.WriteLine(Encoding.UTF8.GetString(compressBuff));
        //Uncompress not working below by using string
        //The magic number in GZip header is not correct
        try
        {
            var uncompressFromString = GZip.GZipUncompress(compressBuff);
            Console.WriteLine("uncompress successful by uncompress string");
        }
        catch
        {
            Console.WriteLine("uncompress failed by uncompress string");
        }

code for class Gzip

public static class GZip
      {
        public static byte[] GZipUncompress(byte[] data)
        {
            using (var input = new MemoryStream(data))
            using (var gzip = new GZipStream(input, CompressionMode.Decompress))
            using (var output = new MemoryStream())
            {
                gzip.CopyTo(output);
                return output.ToArray();
            }
        }
        public static byte[] GZipCompress(byte[] data)
        {
            using (var input = new MemoryStream(data))
            using (var output = new MemoryStream())
            {
                using (var gzip = new GZipStream(output, CompressionMode.Compress, true))
                {
                    input.CopyTo(gzip);
                }
                return output.ToArray();
            }
        }

        public static long CopyTo(this Stream source, Stream destination)
        {
            var buffer = new byte[2048];
            int bytesRead;
            long totalBytes = 0;
            while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
            {
                destination.Write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }
            return totalBytes;
        }
}

Upvotes: 0

Views: 4147

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1500695

This is inappropriate:

var compressString = Encoding.UTF8.GetString(compress);

compress isn't a UTF-8-encoded piece of text. You should treat it as arbitrary binary data - which isn't appropriate to pass into Encoding.GetString. If you really need to convert arbitrary binary data into text, use Convert.ToBase64String (and then reverse with Convert.FromBase64String):

var compressString = Convert.ToBase64String(compress);
Console.WriteLine(compressString);
var compressBuff = Convert.FromBase64String(compressString);

That may or may not match what PHP does, but it's a safe way of representing arbitrary binary data as text, unlike treating the binary data as if it were valid UTF-8-encoded text.

Upvotes: 6

Darin Dimitrov
Darin Dimitrov

Reputation: 1038850

I am trying to replicate the php function gzuncompress in C#

Then use GZipStream or DeflateStream classes which are built into the .NET framework for this purpose.

Upvotes: 1

Related Questions