GZipStream 在写入 FileStream 时有效,但不适用于 MemoryStream
GZipStream works when writing to FileStream, but not MemoryStream
如果压缩一些 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
子句之外似乎可行。但是,这会关闭大多数用法的输出流。即:
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 上失败,因为流已关闭。我知道我可以从 output.ToArray()
的字节创建一个新的 Stream
,但为什么这是必要的?为什么 ToArray()
在流关闭时工作?
最终编辑:
只需要使用 GZipStream
的构造函数和 leaveOpen
参数。
您在关闭 GZipStream
之前调用 ToArray()
... 这意味着它还没有机会刷新其缓冲区的最后几位。这是压缩加密流的常见问题,关闭流需要写入一些最终数据。 (例如,即使显式调用 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
时,流将被释放,但没关系。)
如果压缩一些 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
子句之外似乎可行。但是,这会关闭大多数用法的输出流。即:
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 上失败,因为流已关闭。我知道我可以从 output.ToArray()
的字节创建一个新的 Stream
,但为什么这是必要的?为什么 ToArray()
在流关闭时工作?
最终编辑:
只需要使用 GZipStream
的构造函数和 leaveOpen
参数。
您在关闭 GZipStream
之前调用 ToArray()
... 这意味着它还没有机会刷新其缓冲区的最后几位。这是压缩加密流的常见问题,关闭流需要写入一些最终数据。 (例如,即使显式调用 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
时,流将被释放,但没关系。)