C#MemoryStream和GZipInputStream:不能。读取超过256个字节

问题描述 投票:2回答:1

我在使用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的限制?

c# memorystream gzipinputstream
1个回答
1
投票

从流中读取时,您需要循环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);
}
© www.soinside.com 2019 - 2024. All rights reserved.