我在使用SharpZipLib的GZipInputStream编写未压缩的GZIP流时遇到问题。我似乎只能获得价值256字节的数据,而其余的数据不会被写入并置零。已检查压缩流(compressedSection),并且所有数据都存在(1500+字节)。减压过程的代码段如下:
int msiBuffer = 4096;
using (Stream msi = new MemoryStream(msiBuffer))
{
msi.Write(compressedSection, 0, compressedSection.Length);
msi.Position = 0;
int uncompressedIntSize = AllMethods.GetLittleEndianInt(uncompressedSize, 0); // Gets little endian value of uncompressed size into an integer
// SharpZipLib GZip method called
using (GZipInputStream decompressStream = new GZipInputStream(msi, uncompressedIntSize))
{
using (MemoryStream outputStream = new MemoryStream(uncompressedIntSize))
{
byte[] buffer = new byte[uncompressedIntSize];
decompressStream.Read(buffer, 0, uncompressedIntSize); // Stream is decompressed and read
outputStream.Write(buffer, 0, uncompressedIntSize);
using (var fs = new FileStream(kernelSectionUncompressed, FileMode.Create, FileAccess.Write))
{
fs.Write(buffer, 0, buffer.Length);
fs.Close();
}
outputStream.Close();
}
decompressStream.Close();
因此,在此代码段中:
1)压缩段已传入,准备进行解压缩。
2)未压缩输出的预期大小(存储在标头中,文件为2字节Little-Endian值)通过一种方法传递,以将其转换为整数。标头较早删除,因为它不属于压缩的GZIP文件。
3)SharpLibZip的GZIP流使用压缩文件流(msi)和等于int uncompressedIntSize的缓冲区声明(也已经测试了4096的静态值)。
4)我设置了一个MemoryStream来处理将输出写入文件的过程,因为GZipInputStream没有读/写功能;它以预期的解压缩文件大小作为参数(容量)。
5)流的读/写需要byte []数组作为第一个参数,因此我设置了一个byte []数组,该数组具有足够的空间来容纳解压缩输出的所有字节(在这种情况下为3584字节,派生来自uncompressedIntSize)。
6)int GzipInputStream decompressStream使用.Read将缓冲区作为第一个参数,从偏移量0开始,使用uncompressedIntSize作为计数。检查此处的参数,缓冲区数组的容量仍为3584字节,但仅获得256字节的数据。其余为零。
看起来.Read的输出被限制为256个字节,但是我不确定在哪里。我是否已经错过了Streams,或者这是.Read的限制?
从流中读取时,您需要循环; lazy方法可能是:
decompressStream.CopyTo(outputStream);
(但是不能保证在uncompressedIntSize
个字节后停止-它将尝试读取到decompressStream
的末尾)
更手动的版本(遵守所施加的长度限制)将是:
const int BUFFER_SIZE = 1024; // whatever
var buffer = ArrayPool<byte>.Shared.Rent(BUFFER_SIZE);
try
{
int remaining = uncompressedIntSize, bytesRead;
while (remaining > 0 && // more to do, and making progress
(bytesRead = decompressStream.Read(
buffer, 0, Math.Min(remaining, buffer.Length))) > 0)
{
outputStream.Write(buffer, 0, bytesRead);
remaining -= bytesRead;
}
if (remaining != 0) throw new EndOfStreamException();
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}