.net 将JSON(System.Text.Json)序列化为GZipStream和MemoryStream

6l7fqoea  于 2023-03-04  发布在  .NET
关注(0)|答案(1)|浏览(149)

我在内存中有一个对象,我想在压缩数据时使用System.Text.Json.JsonSerializer对其进行序列化(并保留流以供以后使用,特别是使用Stream InputStream将其传递到S3 SDK以放入存储)。

await using var stream = new MemoryStream(); // <- compressed content stored here
await using var gzip = new GZipStream(stream, CompressionLevel.Optimal); // <- compression

await JsonSerializer.SerializeAsync(gzip, myObject); // <- serialize
gzip.Flush(); // <- make sure everything is flushed

此时,stream包含JSON序列化myObject的压缩二进制数据,最后,我希望将此数据存储到一个文件中-本地或存储到S3(使用Amazon.S3.Transfer.TransferUtility,将stream传递给InputStream属性)。

  • 如何将内容保存到文件(使用文件流会产生无效的.gz文件)?
  • 如何指定.gz包中内容所放置文件(名称)?
omtl5h9j

omtl5h9j1#

  • 如何将内容保存到文件(使用文件流会产生无效.gz文件)?

您需要将MemoryStream的位置重新设置为0,否则没有任何内容可供读取。

stream.Position = 0;
await using (var file = new FileStream(@"someFile.gz", FileMode.Create, FileAccess.ReadWrite))
{
    await file.CopyToAsync(stream);
}
stream.Position = 0;

或者,您可以使用流内部的底层数组,这可能会更有效。您仍然应该在将流发送到S3之前重置流位置。

await using (var file = new FileStream(@"someFile.gz", FileMode.Create, FileAccess.ReadWrite))
{
    await file.Write(stream.GetBuffer(), 0, stream.Length);
}
stream.Position = 0;

注意在函数结束之前使用大括号来正确地刷新和关闭文件。你应该这样做而不是Flush

  • 如何指定.gz包中内容所放置文件(名称)?

你不能。gzip 规范中没有添加文件名的机制,它是为压缩单个文件而设计的。通常你会先生成一个 tarball,或者使用ZipArchive,它使用类似的压缩算法。

相关问题