【问题标题】:.NET GZipStream compress and decompress.NET GZipStream 压缩和解压
【发布时间】:2009-10-19 20:14:24
【问题描述】:

下面这段代码有什么问题。我总是得到 FALSE,意思是压缩后,解压后的数据与原始值不匹配。

public static bool Test()
        {
            string sample = "This is a compression test of microsoft .net gzip compression method and decompression methods";
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            byte[] data = encoding.GetBytes(sample);
            bool result = false;

            //Compress
            MemoryStream cmpStream;
            cmpStream = new MemoryStream();
            GZipStream hgs = new GZipStream(cmpStream, CompressionMode.Compress);
            hgs.Write(data, 0, data.Length);
            byte[] cmpData = cmpStream.ToArray();

            MemoryStream decomStream;
            decomStream = new MemoryStream(cmpData);
            hgs = new GZipStream(decomStream, CompressionMode.Decompress);
            hgs.Read(data, 0, data.Length);

            string sampleOut = System.BitConverter.ToString(data);

            result = String.Equals(sample, sampleOut) ;
            return result;
        }

如果您能指出我在哪里犯了错误,我将不胜感激。

【问题讨论】:

    标签: .net compression gzipstream


    【解决方案1】:

    Write 调用之后关闭GZipStream

    如果不调用Close,则有可能某些数据已被缓冲并且尚未写入底层流。

    【讨论】:

    • @Blindy:我刚刚检查过 Reflector。只有Close 是一个选项。 Flush 什么都不做。
    • 是的,我在压缩和解压缩后都尝试关闭,仍然无法正常工作。出于某种原因 hgs.Read( ... ) 没有读取任何内容 :: 这就是问题所在。无论是否使用 hgs.close(),问题仍然存在。如果您对 close() 或 flush() 如此确定,您可以粘贴您的工作代码吗?非常感谢。 =-- Mehdi Anis --=
    • 正确 - 不要冲洗 - 关闭它。调试了一个小时,直到我弄清楚了。
    • 完全是我很久之后的想法。
    【解决方案2】:

    试试这个代码:

    public static bool Test()
            {
                string sample = "This is a compression test of microsoft .net gzip compression method and decompression methods";
    
                System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    
                byte[] data = encoding.GetBytes(sample);
                bool result = false;
    
                // Compress
                MemoryStream cmpStream = new MemoryStream();
    
                GZipStream hgs = new GZipStream(cmpStream, CompressionMode.Compress);
    
                hgs.Write(data, 0, data.Length);
    
                byte[] cmpData = cmpStream.ToArray();
    
                MemoryStream decomStream = new MemoryStream(cmpData);
    
                hgs = new GZipStream(decomStream, CompressionMode.Decompress);
                hgs.Read(data, 0, data.Length);
    
                string sampleOut = encoding.GetString(data);
    
                result = String.Equals(sample, sampleOut);
                return result;
            }
    

    问题是你没有使用 ASCIIEncoder 来获取 sampleData 的字符串。

    编辑:这是代码的清理版本,以帮助关闭/处置:

    public static bool Test()
            {
                string sample = "This is a compression test of microsoft .net gzip compression method and decompression methods";
    
                System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    
                byte[] data = encoding.GetBytes(sample);
    
                // Compress.
                GZipStream hgs;
                byte[] cmpData;
    
                using(MemoryStream cmpStream = new MemoryStream())
                using(hgs = new GZipStream(cmpStream, CompressionMode.Compress))
                {
                    hgs.Write(data, 0, data.Length);
                    hgs.Close()
    
                    // Do this AFTER the stream is closed which sounds counter intuitive 
                    // but if you do it before the stream will not be flushed
                    // (even if you call flush which has a null implementation).
                    cmpData = cmpStream.ToArray();
                }  
    
                using(MemoryStream decomStream = new MemoryStream(cmpData))
                using(hgs = new GZipStream(decomStream, CompressionMode.Decompress))
                {
                    hgs.Read(data, 0, data.Length);
                }
    
                string sampleOut = encoding.GetString(data);
    
                bool result = String.Equals(sample, sampleOut);
                return result;
            }
    

    【讨论】:

    • 是的!有用!但实际问题仍然存在。它作为数据中的值未更改。如果我使用“data = new byte[data.Length];”重置 data[]就在调用 hgs.read(... .. .) 之前,result=false。因为, hgs.Read 完全失败了。它什么也不读。如果您输入“readCount=hgs.Read(...)”,您将看到 readCount=0,这意味着没有读取任何内容。这就是我面临的问题。希望你能有所启发。谢谢。非常感谢大家的快速回复。
    • 对不起,如果我在这里误解了,但你是说如果你把'data = new byte[data.Length];'在 'hgs.Read()' 调用之前,结果是否为假?这是我所期望的,因为此时 data[] 数组的值正在被擦除。不确定我是否理解这里的事情,我必须再喝点咖啡! :)
    • 我知道这是一个老问题,但@MehdiAnis 是正确的。此代码不起作用。观察 hgs.Read(data, 0, data.Length) 的返回值,你会看到它是零。
    • 在将压缩字节复制到数组之前,您必须关闭()压缩 GZipStream。
    • @JasonEvans 我改变了 ToArray() 调用的时间,否则根据其他 cmets 它不起作用。无论是那个投票还是投反对票,我认为没有理由投反对票一个非常好的答案。
    【解决方案3】:

    要解决这个问题,需要解决三个问题。 1. WRITE GZipStream 后需要关闭 :: hgs.Close();

    1. 需要使用 WHILE 循环读取 GZipStream 并将未压缩数据的较小缓冲区写入 MemoryStream :: outStream.Write( ... );

    2. 解压后的byte[]数组的转换需要用到编码转换 :: string sampleOut = encoding.GetString(data);

    这是最终代码:-

    public static bool Test()
            {
                string sample = "This is a compression test of microsoft .net gzip compression method and decompression methods";
                System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                byte[] data = encoding.GetBytes(sample);
                bool result = false;
    
                // Compress 
                MemoryStream cmpStream = new MemoryStream();
                GZipStream hgs = new GZipStream(cmpStream, CompressionMode.Compress, true);
    
                hgs.Write(data, 0, data.Length);
                hgs.Close();
    
    
                //DeCompress
                byte[] cmpData = cmpStream.ToArray();
                MemoryStream decomStream = new MemoryStream(cmpData);
    
                data = new byte[data.Length];
                hgs = new GZipStream(decomStream, CompressionMode.Decompress, true);
    
                byte[] step = new byte[16]; //Instead of 16 can put any 2^x
                MemoryStream outStream = new MemoryStream();
                int readCount;
    
                do
                {
                    readCount = hgs.Read(step, 0, step.Length);
                    outStream.Write(step, 0, readCount);
                } while (readCount > 0);
                hgs.Close();
    
                string sampleOut = encoding.GetString(outStream.ToArray());
                result = String.Equals(sample, sampleOut);
                return result; 
            }
    

    我很难使用 Microsoft .NET GZipStream 对象进行压缩/解压缩工作。最后,我认为我得到了正确的方法。非常感谢大家,因为解决方案来自你们所有人。

    【讨论】:

      【解决方案4】:

      这是我整理后的最终解决方案:

      
        [Test]
        public void Test_zipping_with_memorystream()
        {
         const string sample = "This is a compression test of microsoft .net gzip compression method and decompression methods";
         var encoding = new ASCIIEncoding();
         var data = encoding.GetBytes(sample);
         string sampleOut;
         byte[] cmpData;
      
         // Compress 
         using (var cmpStream = new MemoryStream())
         {
          using (var hgs = new GZipStream(cmpStream, CompressionMode.Compress))
          {
           hgs.Write(data, 0, data.Length);
          }
          cmpData = cmpStream.ToArray();
         }
      
         using (var decomStream = new MemoryStream(cmpData))
         {
          using (var hgs = new GZipStream(decomStream, CompressionMode.Decompress))
          {
           using (var reader = new StreamReader(hgs))
           {
            sampleOut = reader.ReadToEnd();
           }
          }
         }
      
         Assert.IsNotNullOrEmpty(sampleOut);
         Assert.AreEqual(sample, sampleOut);
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多