压缩流

时间:2014-02-28 04:17:21

标签: c# stream compression

我一直在尝试在我的一个程序中实现压缩方法。我希望它接收流,压缩它,然后返回压缩流(它返回一个流,因为我希望能够将流传递给另一个函数,而不必将其保存到文件中并稍后重新读取) 。我有一个基于GZipStream的msdn示例的工作测试版本,这是我在尝试将其转换为接收和返回流时的想法:

public static Stream compress(Stream fileToCompress)
{
    using (MemoryStream compressedFileStream = new MemoryStream())
    {
        using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
        {
            fileToCompress.CopyTo(compressionStream);
            return compressionStream;
        }
    }
}

将返回的流保存到文件中(在另一种方法中)会导致创建一个0字节的文件(非常有效的压缩,是吗?)。

我尝试过查找other solutions,但我找不到任何使用流的内容,而且我的转换尝试遇到了同样的问题。

编辑:仅仅为了记录,我尝试使用DeflateStream来获得相同的结果。

EDIT2:原来是测试程序无法正常保存。谢谢你的帮助。

2 个答案:

答案 0 :(得分:2)

如果您的目标是返回流,则需要将其放在using块中。

这样的事情:

public static Stream compress(Stream fileToCompress) {
    MemoryStream compressedFileStream = new MemoryStream();
    GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress);
    fileToCompress.CopyTo(compressionStream);
    compressionStream.Seek(0, SeekOrigin.Begin); // Reset to stream start.
    return compressionStream;
}

否则,当流离开using块时,它会在流上调用Dispose()

编辑:此外,在复制之后,流“指针”在最后。您需要将指针设置回开始。保存之前 - 显示在这里。

编辑:删除所有使用块。如果您需要发布流,可以手动执行。

答案 1 :(得分:0)

您可以按照Steven Hansen的建议跳过using / Dispose来电,但使用压缩数据返回MemoryStream的新副本可能更为清晰。

public static Stream compress(Stream fileToCompress)
{
    using (MemoryStream compressedFileStream = new MemoryStream())
    {
        using (var compressionStream = new GZipStream(
             compressedFileStream, CompressionMode.Compress))
        {
            fileToCompress.CopyTo(compressionStream);
        }
        return new MemoryStream(compressionStream.ToArray());
    }
}

如果你想保留单个内存流 - 使用调用删除,不要忘记重新定位流。

var compressedFileStream = new MemoryStream();
var compressionStream = new GZipStream(
           compressedFileStream, CompressionMode.Compress);
fileToCompress.CopyTo(compressionStream);
 // Flush to make sure all data written by compression stream.
compressionStream.Flush();
compressedFileStream.Position = 0;
return compressedFileStream;

请注意,如果文件非常大,使用临时文件来存储压缩/未压缩的流可能会因MemoryStream中使用的内存分配策略而更快 - 请尝试并测量。