我想知道是否有人可以解释一个让我疯狂的问题:
我正在编写一个压缩解压缩测试类。为了测试它,我将数据集序列化为内存流,压缩它,解压缩并比较结果。
压缩很好,但是压缩是打击污垢的地方。 这是解压缩功能:
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增加一个字节,那么一切都很好(除了丢失的字节)
缓冲区大小为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]
1589544的缓冲区(代码槽中的一些神奇数字)
bytesRead: [189544] outStream.Length [189544]
bytesRead: [0] outStream.Length [189544]
total bytes read [189544]
Unompressed stream size 189544
另请注意第三次读取buffersize 65536 ex:bytesRead:[58472]显然这也应该是65536,因为缓冲区上还有数据?
任何想法都将非常赞赏。
TIA
答案 0 :(得分:5)
您应该始终在压缩流上调用Close()。请注意,Flush()不够。我怀疑因此,deflate流缺少数据。
答案 1 :(得分:3)
我的通灵能力告诉我,你确实有一个有效的解压缩实现,但忘记了之前刷新压缩流。
答案 2 :(得分:0)
好吧,我无法发现您的问题,但请遵循我之前为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);