8

所以这里有一个奇怪的。我有这种方法来获取 Base64 编码的压缩字符串并返回原始数据:

public static string Base64Decompress(string base64data)
{
    byte[] b = Convert.FromBase64String(base64data);
    using (var orig = new MemoryStream(b))
    {
        using (var inflate = new MemoryStream())
        {
            using (var ds = new DeflateStream(orig, CompressionMode.Decompress))
            {
                ds.CopyTo(inflate);
                return Encoding.ASCII.GetString(inflate.ToArray());
            }
        }
    }
}

这将返回一个空字符串,除非我添加第二次调用ds.CopyTo(inflate). (WTF?)

   ...
            using (var ds = new DeflateStream(orig, CompressionMode.Decompress))
            {
                ds.CopyTo(inflate);
                ds.CopyTo(inflate);
                return Encoding.ASCII.GetString(inflate.ToArray());
            }
   ...

( Flush// on没有效果。Close)Disposeds

为什么DeflateStream在第一次调用时复制 0 个字节?我也试过用 循环Read(),但它在第一次调用时也返回零,然后在第二次调用。


更新:这是我用来压缩数据的方法。

public static string Base64Compress(string data, Encoding enc)
{
    using (var ms = new MemoryStream())
    {
        using (var ds = new DeflateStream(ms, CompressionMode.Compress))
        {
            byte[] b = enc.GetBytes(data);
            ds.Write(b, 0, b.Length);
            ds.Flush();
            return Convert.ToBase64String(ms.ToArray());
        }
    }
}
4

1 回答 1

7

当压缩字节不完整(即,并非所有块都被写出)时,就会发生这种情况。

如果我将 Base64Compress 与以下 Decompress 方法一起使用,我将收到 InvalidDataException 消息“未知块类型。流可能已损坏。

解压

public static string Decompress(Byte[] bytes)
{
  using (var uncompressed = new MemoryStream())
  using (var compressed = new MemoryStream(bytes))
  using (var ds = new DeflateStream(compressed, CompressionMode.Decompress))
  {
    ds.CopyTo(uncompressed);
    return Encoding.ASCII.GetString(uncompressed.ToArray());
  }
}

请注意,使用以下 Compress 方法时,一切都按预期工作

public Byte[] Compress(Byte[] bytes)
{
  using (var memoryStream = new MemoryStream())
  {
    using (var deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress))
      deflateStream.Write(bytes, 0, bytes.Length);

    return memoryStream.ToArray();
  }
}

更新

糟糕,愚蠢的我......在你处理 DeflateStream 之前你不能 ToArray 内存流(因为刷新实际上没有实现(并且 Deflate/GZip 压缩数据块);最后一个块仅在关闭/处理时写入。

重写压缩为:

public static string Base64Compress(string data, Encoding enc)
{
  using (var ms = new MemoryStream())
  {
    using (var ds = new DeflateStream(ms, CompressionMode.Compress))
    {
      byte[] b = enc.GetBytes(data);
      ds.Write(b, 0, b.Length);
    }

    return Convert.ToBase64String(ms.ToArray());
  }
} 
于 2010-11-11T20:56:45.393 回答