GZipStream在写入FileStream时有效,但不能用于MemoryStream

时间:2016-01-13 19:43:30

标签: c# .net gzipstream

如果压缩一些json文本,并使用FileStream将其写入文件,我会得到预期的结果。但是,我不想写入磁盘。我只想要压缩数据的内存流。

压缩为FileStream

string json = Resource1.json;

using (MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes(json)))
using (FileStream output = File.Create(@"C:\Users\roarker\Desktop\output.json.gz"))
{
    using (GZipStream compression = new GZipStream(output, CompressionMode.Compress))
    {
        input.CopyTo(compression);
    }
}

以上作品。下面,输出内存流的长度为10,并产生一个空的.gz文件。

string json = Resource1.json;

using (MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes(json)))
using (MemoryStream output = new MemoryStream())
{
    using (GZipStream compression = new GZipStream(output, CompressionMode.Compress))
    {
        input.CopyTo(compression);

        byte[] bytes = output.ToArray();
    }
}

修改output.ToArray()移到内部using子句之外似乎有效。但是,这会关闭大多数用法的输出流。 IE:

        using (MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes(json)))
        using (MemoryStream output = new MemoryStream())
        {
            using (GZipStream compression = new GZipStream(output, CompressionMode.Compress))
            {
                input.CopyTo(compression);
            }
            WriteToFile(output);
        }

其中:

    public static void WriteToFile(Stream stream)
    {
        using (FileStream output = File.Create(@"C:\Users\roarker\Desktop\output.json.gz"))
        {
            stream.CopyTo(output);
        }
    }

这将在stream.CopyTo失败,因为该流已关闭。我知道我可以从Stream的字节创建一个新的output.ToArray(),但为什么这是必要的?为什么ToArray()在流关闭时有效?

最终修改:

只需使用带有GZipStream参数的leaveOpen的构造函数。

1 个答案:

答案 0 :(得分:10)

在您关闭ToArray()之前,您正在调用GZipStream ...这意味着它没有机会刷新其缓冲区的最后一位。这是压缩加密流的常见问题,关闭流需要编写一些最终的数据。 (例如,即使打电话给Flush()也明确没有帮助。)

只需移动ToArray来电:

using (MemoryStream input = new MemoryStream(Encoding.UTF8.GetBytes(json)))
using (MemoryStream output = new MemoryStream())
{
    using (GZipStream compression = new GZipStream(output, CompressionMode.Compress))
    {
        input.CopyTo(compression);
    }
    byte[] bytes = output.ToArray();
    // Use bytes
}

(请注意,当您拨打ToArray时,系统会处理该流,但这没关系。)