C#MemoryStream和GZipInputStream:无法读取超过256个字节

时间:2019-10-09 16:00:51

标签: c# memorystream gzipinputstream

使用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个字节,但是我不确定在哪里。流是否有我想念的东西,还是.Read的限制?

2 个答案:

答案 0 :(得分:2)

从流中读取时,您需要循环 lazy 的方式可能是:

const_pointer_cast

(但这不能保证在const something个字节后停止-它将尝试读取到decompressStream.CopyTo(outputStream); 的末尾)

更手动的版本(遵守所施加的长度限制)将是:

uncompressedIntSize

答案 1 :(得分:0)

这个问题原来是我先前在发布的代码中所做的疏忽:

我正在使用的文件有27个节,这些节是GZipped的,但是每个节都有一个标头,如果GZipInput流中的任何一个被击中,它们都会破坏Gzip解压缩。打开基础文件时,它每次都是从头开始(调整为6以避开第一个标头),而不是转到下一个后标头偏移:

brg.BaseStream.Seek(6,SeekOrigin.Begin);

代替:

brg.BaseStream.Seek(absoluteSectionOffset,SeekOrigin.Begin);

这意味着提取的压缩数据是第一个无标题的节+第二节的一部分及其标题的混合物。由于第一部分的长度为256个字节,没有标题,因此该部分已由GZipInput流正确解压缩。但是之后有6个字节的标头将其破坏,导致其余输出为00s。

发生这种情况时,GZipInput流没有引发任何显式错误,因此我错误地认为原因是.Read或流中保留前一遍数据的某些内容。抱歉麻烦了。