SharpZipLib压缩字符串

时间:2012-03-22 20:59:43

标签: c# sharpziplib

我需要压缩字符串以减少Web服务响应的大小。我看到SharpZipLib样本中的单元测试,但不是我需要的一个例子。

在下面的代码中,ZipOutputStream的构造函数返回异常:"没有打开的条目"

        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);

我在哪里偏离轨道?我是否比现在更复杂?

5 个答案:

答案 0 :(得分:4)

对于来自Silverlight的Web服务通信压缩数据,我使用此代码段:

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. 预计文本将从类似环境中读/写,因此我没有进行任何额外的编码/解码。
  3. 我的情况是压缩了json数据。根据我的观察,在某些情况下,大约95Kb的文本数据被压缩到1.5Kb。因此,即使将数据序列化为基数64,无论如何都可以节省大量流量。

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

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:2)

您的代码存在一些问题:

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

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

    byte [] data = ms.ToArray();

  3. Zip文件是可能包含多个条目(文件),注释的容器......您可能需要调用PutNextEntry()以在开始向其写入数据之前添加新条目。

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

答案 3 :(得分:1)

在编写数据之前,您需要调用PutNextEntry来添加标题。

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

答案 4 :(得分:0)

我发现最简单的答案是在解压缩/压缩数据时处理字节,并使用set size buffer将数据复制到Stream对象,可以随意使用:

ViewModel