压缩和解压缩源数据给出的结果与源数据不同

时间:2010-10-03 00:11:18

标签: c# stream deflate

在我的应用程序中,我需要将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;
    }
}

如果可以,请帮助我解决此案。 最好的祝福, 亚当

1 个答案:

答案 0 :(得分:3)

(已编辑:从使用flush切换,仍然可能无法清除所有字节,现在确保首先处理deflate,根据Phil的回答: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将大于缓冲区的长度,这意味着它总是将负值传递给stream.Read以获取要读取的字节数。我的猜测是,它永远不会读取第二个块,返回零,并从while循环中掉出来。

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