GZipStream压缩未生效

7
我将尝试读取文件并使用GZipStream进行压缩,如下所示:

using (var outStream = new MemoryStream())
{
    using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        using (var gzipStream = new GZipStream(outStream, CompressionMode.Compress))
        {
            fileStream.CopyTo(gzipStream);

            Debug.WriteLine(
                "Compressed from {0} to {1} bytes", 
                fileStream.Length, 
                outStream.Length);

            // "outStream" is utilised here (persisted to a NoSql database).
        }
    }
} 

问题在于outStream.Length总是显示10个字节。我做错了什么?
我已经尝试在fileStream.CopyTo行之后调用gzipStream.Close()(如其他论坛中建议的那样),但这似乎也关闭了outStream,因此随后使用它的代码会失败。

根据MSDN的说法,不能太依赖Stream.length属性,因为它可能已经被实现或未被实现。你是否通过其他手段检查过得到的outstream是否不正确? - C4stor
1个回答

6

MSDN表示:写操作可能不会立即发生,而是缓冲区达到大小或调用Flush或Close方法之前被缓冲。

换句话说,所有的写操作都完成并不意味着数据已经在MemoryStream中。您必须先执行gzipStream.Flush()或关闭gzipStream。

示例:

using (var outStream = new MemoryStream())
{
    using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        using (var gzipStream = new GZipStream(outStream, CompressionMode.Compress))
        {
            fileStream.CopyTo(gzipStream);
        }

        Debug.WriteLine(
                "Compressed from {0} to {1} bytes", 
                fileStream.Length, 
                outStream.Length);

        // "outStream" is utilised here (persisted to a NoSql database).
    }
} 

此外,最好将其放在 FileStream 之外 - 您希望尽早关闭文件,而不是等待其他处理完成。

2
起初我怀疑缺少刷新是罪魁祸首,但是GZipStream.Flush文档明确说明“此方法的当前实现没有功能”,关闭流确实是唯一的选择。 - O. R. Mapper
2
@O.R.Mapper: ILSpy似乎证实了这一点。哇,有点过分了。我想他们没有办法去实现它,因为它不能增量工作,你可能需要一次压缩和写入所有数据。 - Luaan
1
那个方法不起作用 - 在fileStream.CopyTo()周围加上using(或者在CopyTo之后关闭gzipStream,如我问题中所提到的)会导致outStream也关闭,使其在后续行中无法使用。 - Andrew Stephens
4
是的,GZipStream构造函数的第三个参数就是用来控制这个的。如果你使用new GZipStream(outStream, CompressionMode.Compress, true),它应该会保持outStream处于打开状态。别忘了倒带MemoryStream (outStream.Position = 0;)。 - Luaan
第三个参数起了作用,谢谢!已标记为已回答。 - Andrew Stephens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接