gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 22:43:40 28 4
gpt4 key购买 nike

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

如果可以,请帮我解决这个问题。此致,亚当

最佳答案

(编辑:从使用 flush 切换到现在确保首先处理 deflate,这仍然可能不会清除所有字节,根据 Phil 在这里的回答:zip and unzip string with Deflate)

在尝试从后备存储中读取之前,您必须确保 deflate 流在压缩时已完全刷新自身,从而允许 deflate 完成压缩并写入最终字节。关闭放气 Steam 或将其处理掉即可实现这一目标。

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)

当读取第二个 block 时,read 将大于缓冲区的长度,这意味着它总是将一个负值传递给 stream.Read 作为要读取的字节数。我的猜测是它永远不会读取第二个 block ,返回零,然后退出 while 循环。

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

关于c# - 压缩和解压缩源数据给出的结果与源数据不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3848021/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com