【问题标题】:SharpZipLib to compress a stringSharpZipLib 压缩字符串
【发布时间】:2012-03-22 20:59:42
【问题描述】:

我需要压缩字符串以减小 Web 服务响应的大小。我在 SharpZipLib 示例中看到了单元测试,但并不是我所需要的示例。

在以下代码中,ZipOutputStream 的构造函数返回异常:“No open entry”

        byte[] buffer = Encoding.UTF8.GetBytes(SomeLargeString);
        Debug.WriteLine(string.Format("Original byes of string: {0}", buffer.Length));

        MemoryStream ms = new MemoryStream();
        using (ZipOutputStream zipStream = new ZipOutputStream(ms))
        {
            zipStream.Write(buffer, 0, buffer.Length);
            Debug.WriteLine(string.Format("Compressed byes: {0}", ms.Length));
        }

        ms.Position = 0;
        MemoryStream outStream = new MemoryStream();

        byte[] compressed = new byte[ms.Length];
        ms.Read(compressed, 0, compressed.Length);

        byte[] gzBuffer = new byte[compressed.Length + 4];
        System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
        System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
        string compressedString = Convert.ToBase64String (gzBuffer);

我在哪里偏离了轨道?我是否让这变得比它应该的更复杂?

【问题讨论】:

    标签: c# sharpziplib


    【解决方案1】:

    对于来自 Silverlight 的 Web 服务通信压缩数据,我使用这个 sn-p:

    private byte[] zipText(string text)
    {
        if (text == null)
            return null;
    
        using(Stream memOutput = new MemoryStream())
        {
            using (GZipOutputStream zipOut = new GZipOutputStream(memOutput))
            {
                using (StreamWriter writer = new StreamWriter(zipOut))
                {
                    writer.Write(text);
    
                    writer.Flush();
                    zipOut.Finish();
    
                    byte[] bytes = new byte[memOutput.Length];
                    memOutput.Seek(0, SeekOrigin.Begin);
                    memOutput.Read(bytes, 0, bytes.Length);
    
                    return bytes;
                }
            }
        }
    }
    
    private string unzipText(byte[] bytes)
    {
        if (bytes == null)
            return null;
    
        using(Stream memInput = new MemoryStream(bytes))
        using(GZipInputStream zipInput = new GZipInputStream(memInput))
        using(StreamReader reader = new StreamReader(zipInput))
        {
            string text = reader.ReadToEnd();
    
            return text;
        }
    }
    
    1. 我使用 GZip 而不是 Zip 压缩
    2. 预计文本将从类似的环境中读取/写入,因此我没有进行任何额外的编码/解码。

    我的案例是 json 数据的压缩。根据我的观察,在某些情况下,大约 95Kb 的文本数据被压缩到 1.5Kb。所以即使数据会被序列化成base 64,反正是很好的节省流量。

    发布我的答案可能会为某人节省一些时间。

    【讨论】:

      【解决方案2】:

      您确定将数据转换为 Base 64 后数据会小得多吗?这将使二进制数据(zip)显着膨胀。您不能使用 HTTP 压缩在传输级别解决问题吗?

      这是一篇包含完整源代码的帖子,展示了如何进行往返压缩/解压缩。

      http://paultechguy.blogspot.com/2008/09/zip-xml-in-memory-for-web-service.html

      【讨论】:

        【解决方案3】:

        您的代码存在一些问题:

        1. 使用流时始终刷新数据。

        2. 要从 MemoryStream 中读取数据,只需使用:

          byte[] 数据 = ms.ToArray();

        3. Zip 文件是可能包含多个条目(文件)、cmets 的容器……您可能需要调用 PutNextEntry() 来添加新条目,然后再开始向其中写入数据。

        4. 如果您只需要压缩单个数据流(这是您的情况),您最好的选择是简单地使用 deflate(或 gzip)压缩,它旨在压缩单个数据流(实际上是 zip格式在内部使用 gzip 压缩其条目...) .Net 提供了 2 个非常方便的数据压缩类:GZipStream 和 DeflateStream。一个好的样本可以找到here

        【讨论】:

          【解决方案4】:

          在写入数据之前,您需要调用 PutNextEntry 添加表头。

          答案复制自:http://community.sharpdevelop.net/forums/p/5910/16947.aspx

          【讨论】:

            【解决方案5】:

            我发现的最简单的答案是在解压缩/压缩数据时处理字节,并使用设置大小的缓冲区将数据复制到可以随意使用的 Stream 对象:

                /// <summary>
                /// Unzips (inflates) zipped data.
                /// </summary>
                /// <param name="zippedData">The zipped data.</param>
                /// <returns>The inflated data.</returns>
                public Byte[] GUnzip(Byte[] zippedData)
                {
                    using (MemoryStream unzippedData = new MemoryStream())
                    {
                        using (GZipInputStream zippedDataStream = new GZipInputStream(new MemoryStream(zippedData)))
                        {
                            CopyStream(zippedDataStream, unzippedData);
                        }
            
                        return unzippedData.ToArray();
                    }
                }
            
                /// <summary>
                /// zips data.
                /// </summary>
                /// <param name="unzippedData">The unzipped data.</param>
                /// <returns>The zipped data.</returns>
                public Byte[] GZip(Byte[] unzippedData)
                {
                    using (MemoryStream zippedData = new MemoryStream())
                    {
                        using (GZipOutputStream unzippedDataStream = new GZipOutputStream(new MemoryStream(unzippedData)))
                        {
                            CopyStream(unzippedDataStream, zippedData);
                        }
            
                        return zippedData.ToArray();
                    }
                }
            
                /// <summary>
                /// Accepts an inStream, writes it to a buffer and goes out the outStream
                /// </summary>
                /// <param name="inStream">The input Stream</param>
                /// <param name="outStream">The output Stream</param>
                private static void CopyStream(Stream inStream, Stream outStream)
                {
                    int nRead = 0;
                    // Using a 2k buffer
                    Byte[] theBuffer = new Byte[2048];
            
                    while ((nRead = inStream.Read(theBuffer, 0, theBuffer.Length)) > 0)
                    {
                        outStream.Write(theBuffer, 0, nRead);
                    }
                }
            

            【讨论】:

            • 我觉得这种用法有点尴尬......我更喜欢像下面@kikea 的答案那样堆叠流,因为它也摆脱了一个 MemoryStream 实例
            猜你喜欢
            • 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
            相关资源
            最近更新 更多