令人费解的 .Net C# DeflateStream 问题

发布于 2024-08-08 19:14:34 字数 1883 浏览 12 评论 0原文

我想知道是否有人可以阐明一个让我发疯的问题:

我正在编写一个压缩减压测试课程。为了测试它,我将数据集序列化到内存流,压缩它,然后解压缩它并比较结果。

压缩很好,但解压缩就很糟糕了。 这是解压缩函数:

    public static Stream GetUncompressedStreamCopy(Stream inStream)
    {
      Stream outStream = new MemoryStream();

      inStream.Position = 0;

      DeflateStream uncompressStream = new DeflateStream(inStream, 
        CompressionMode.Decompress, true);

      byte[] buffer = new byte[65536];

      int totalread = 0;
      int bytesread = 0;


      do {
        bytesread = uncompressStream.Read(buffer, 0, buffer.Length);
        totalread += bytesread;
        outStream.Write(buffer, 0, bytesread);
        Console.WriteLine("bytesRead: [{0}]\t outStream.Length [{1}]",
        bytesread, outStream.Length);
      } while (bytesread > 0);


      Console.WriteLine("total bytes read [{0}]", totalread);
      outStream.Flush();
      return outStream;
}

对于大小为 65536 的缓冲区,解压缩的流始终返回比未压缩的少一个字节。

现在这让我想到了我正在解决的第二个问题。对于某些缓冲区大小,uncompressStream.Read 返回 0,即使仍有压缩数据需要提取。

对于这些情况,deflateStream.Read(s) 仅在 do{} 循环中一次,然后返回等于 buffersize 的未压缩流,如果将 buffersize 增加一个字节,一切都很好(除了丢失的字节)。

buffersize 为 65536 的输出:(原始未压缩数据为 207833)

bytesRead: [65536]       outStream.Length [65536]
bytesRead: [65536]       outStream.Length [131072]
bytesRead: [58472]       outStream.Length [189544]
bytesRead: [18288]       outStream.Length [207832]
bytesRead: [0]           outStream.Length [207832]
total bytes read [207832]

buffersize 为 189544(代码坦克的一些幻数)

bytesRead: [189544]      outStream.Length [189544]
bytesRead: [0]           outStream.Length [189544]
total bytes read [189544]
Unompressed stream size 189544

还要注意 buffersize 65536 的第三次读取 ex: bytesRead: [58472] 显然这也应该是 65536,因为仍然有数据留在缓冲区?

任何想法都将不胜感激。

蒂亚

  • ·雅科

I wonder if anyone can shed some light on an issue that is driving me nuts:

I am writing a compression decompression test class. To test it, I am serializing a dataset to a memory stream, compressing it, and uncompressing it and comparing the results.

Compression is fine, but uncompression is where it hits the dirt.
This is the decompress function:

    public static Stream GetUncompressedStreamCopy(Stream inStream)
    {
      Stream outStream = new MemoryStream();

      inStream.Position = 0;

      DeflateStream uncompressStream = new DeflateStream(inStream, 
        CompressionMode.Decompress, true);

      byte[] buffer = new byte[65536];

      int totalread = 0;
      int bytesread = 0;


      do {
        bytesread = uncompressStream.Read(buffer, 0, buffer.Length);
        totalread += bytesread;
        outStream.Write(buffer, 0, bytesread);
        Console.WriteLine("bytesRead: [{0}]\t outStream.Length [{1}]",
        bytesread, outStream.Length);
      } while (bytesread > 0);


      Console.WriteLine("total bytes read [{0}]", totalread);
      outStream.Flush();
      return outStream;
}

With a buffer of size 65536 the decompressed stream always returns one byte less than it was uncompressed.

Now this brings me to the second issue which I am battling with. With some buffer sizes, uncompressStream.Read returns 0 even though there is still compressed data left to extract.

For these cases, deflateStream.Read(s) only once in the do{} loop and then returns an uncompressed stream equal to buffersize, if you increase the buffersize by a single byte all is well (except for the missing byte).

Output for buffersize of 65536: (Original uncompressed data is 207833)

bytesRead: [65536]       outStream.Length [65536]
bytesRead: [65536]       outStream.Length [131072]
bytesRead: [58472]       outStream.Length [189544]
bytesRead: [18288]       outStream.Length [207832]
bytesRead: [0]           outStream.Length [207832]
total bytes read [207832]

buffersize of 189544 (Some magic number where the code tanks)

bytesRead: [189544]      outStream.Length [189544]
bytesRead: [0]           outStream.Length [189544]
total bytes read [189544]
Unompressed stream size 189544

Also note the 3rd read of buffersize 65536 ex: bytesRead: [58472] Clearly this should also be 65536 as there still data left on the buffer?

Any ideas will be greatly appreciated.

tia

  • Jaco

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

脱离于你 2024-08-15 19:14:34

您应该始终对压缩流调用 Close()。请注意,Flush() 还不够。我怀疑因此 deflate 流丢失了数据。

You should always call Close() on compression streams. Please note that Flush() is not enough. I suspect that because of this the deflate stream is missing data.

只为一人 2024-08-15 19:14:34

我的心灵力量告诉我,你实际上有一个有效的减压实现,但之前忘记刷新压缩流。

My psychic powers tells me that you do in fact have a working decompression implementation, but have forgotten to flush the compression stream before.

陌路终见情 2024-08-15 19:14:34

好吧,我无法发现你的问题,但请遵循我之前为 ICSharpCode.SharpZipLib< 编写的一些代码/a>;

byte[] compressedData;
using(MemoryStream ms = new MemoryStream())
{
    Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, true);
    Stream s = new DeflaterOutputStream(ms, deflater);
    s.Write(sendData, 0, sendData.Length);
    s.Close();
    compressedData = (byte[])ms.ToArray();
}

// ...

MemoryStream inflated = new MemoryStream();
using (Stream inflater = new InflaterInputStream(
    inputStream, new Inflater(true)))
{
    int count = 0;
    byte[] deflated = new byte[4096];
    while ((count = inflater.Read(deflated, 0, deflated.Length)) != 0)
    {
        inflated.Write(deflated, 0, count);
    }
    inflated.Seek(0, SeekOrigin.Begin);
}
byte[] content = new byte[inflated.Length];
inflated.Read(content, 0, content.Length);

Well, I couldn't spot your problem, but follow some code I wrote sometime ago for ICSharpCode.SharpZipLib;

byte[] compressedData;
using(MemoryStream ms = new MemoryStream())
{
    Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, true);
    Stream s = new DeflaterOutputStream(ms, deflater);
    s.Write(sendData, 0, sendData.Length);
    s.Close();
    compressedData = (byte[])ms.ToArray();
}

// ...

MemoryStream inflated = new MemoryStream();
using (Stream inflater = new InflaterInputStream(
    inputStream, new Inflater(true)))
{
    int count = 0;
    byte[] deflated = new byte[4096];
    while ((count = inflater.Read(deflated, 0, deflated.Length)) != 0)
    {
        inflated.Write(deflated, 0, count);
    }
    inflated.Seek(0, SeekOrigin.Begin);
}
byte[] content = new byte[inflated.Length];
inflated.Read(content, 0, content.Length);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文