2

在我的应用程序中,我需要解压缩 DataContractSerializer 写入的数据以在另一个应用程序中压缩 Deflate Stream,编辑解压缩的数据并再次压缩。

解压缩工作正常,但不适用于我压缩的数据。

问题是当我这样做时: byte[] result = Compressor.Compress(Compressor.Decompress(sourceData));

结果字节数组的长度不同于 sourceData 数组。

例如:

    string source = "test value";
    byte[] oryg = Encoding.Default.GetBytes(source);

    byte[] comp = Compressor.Compress(oryg);
    byte[] result1 = Compressor.Decompress(comp);

    string result2 = Encoding.Default.GetString(res);

这里 result1.Length 是 0 而 result2 是 "" 当然

这是我的 Compressor 类的代码。

public static class Compressor
{
    public static byte[] Decompress(byte[] data)
    {
        byte[] result;

        using (MemoryStream baseStream = new MemoryStream(data))
        {
            using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Decompress))
            {
                result = ReadFully(stream, -1);
            }
        }

        return result;
    }

    public static byte[] Compress(byte[] data)
    {
        byte[] result;

        using (MemoryStream baseStream = new MemoryStream())
        {
            using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Compress, true))
            {
                stream.Write(data, 0, data.Length);
                result = baseStream.ToArray();
            }
        }

        return result;
    }

    /// <summary>
    /// Reads data from a stream until the end is reached. The
    /// data is returned as a byte array. An IOException is
    /// thrown if any of the underlying IO calls fail.
    /// </summary>
    /// <param name="stream">The stream to read data from</param>
    /// <param name="initialLength">The initial buffer length</param>
    private static byte[] ReadFully(Stream stream, int initialLength)
    {
        // If we've been passed an unhelpful initial length, just
        // use 32K.
        if (initialLength < 1)
        {
            initialLength = 65768 / 2;
        }

        byte[] buffer = new byte[initialLength];
        int read = 0;

        int chunk;
        while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
        {
            read += chunk;

            // If we've reached the end of our buffer, check to see if there's
            // any more information
            if (read == buffer.Length)
            {
                int nextByte = stream.ReadByte();

                // End of stream? If so, we're done
                if (nextByte == -1)
                {
                    return buffer;
                }

                // Nope. Resize the buffer, put in the byte we've just
                // read, and continue
                byte[] newBuffer = new byte[buffer.Length * 2];
                Array.Copy(buffer, newBuffer, buffer.Length);
                newBuffer[read] = (byte)nextByte;
                buffer = newBuffer;
                read++;
            }
        }
        // Buffer is now too big. Shrink it.
        byte[] ret = new byte[read];
        Array.Copy(buffer, ret, read);
        return ret;
    }
}

如果可以的话,请帮我处理这个案子。最好的问候,亚当

4

1 回答 1

4

(已编辑:从使用可能仍无法清除所有字节的刷新切换到现在确保首先处理放气,根据菲尔在这里的回答:zip and unzip string with Deflate

在尝试从后备存储读取之前,您必须确保 deflate 流在压缩时已完全刷新,允许 deflate 完成压缩并写入最终字节。关闭放气蒸汽,或将其丢弃,将实现此目的。

public static byte[] Compress(byte[] data)
{
    byte[] result;

    using (MemoryStream baseStream = new MemoryStream())
    {
        using (DeflateStream stream = new DeflateStream(baseStream, CompressionMode.Compress, true))
        {
            stream.Write(data, 0, data.Length);
        }
        result = baseStream.ToArray();  // only safe to read after deflate closed
    }

    return result;
}    

此外,您的 ReadFully 例程看起来非常复杂,并且可能存在错误。一个是:

while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)

读取第二个块时,read将大于缓冲区的长度,这意味着它将始终将负值传递给流。读取要读取的字节数。我的猜测是它永远不会读取第二个块,返回零,并退出 while 循环。

为此,我推荐 Jon 的 ReadFully 版本:Creating a byte array from a stream

于 2010-10-03T00:19:10.923 回答