c# - 包装 JSON 流
问题描述
我正在尝试将大型对象作为 gzip 压缩的 JSON 文本存储到 Azure blob。
我不想将序列化的数据保存在内存中,如果可以避免的话,我也不想假脱机到磁盘,但我不知道如何让它序列化和动态压缩。
我正在使用 Newtonsoft 的 JSON.NET(几乎是 .NET 的事实上的标准 JSON 序列化程序),但这些方法的签名似乎并不真正支持动态流。
Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob
有一个UploadFromStream(Stream source, AccessCondition accessCondition = null, BlobRequestOptions options = null, OperationContext operationContext = null)
方法,但为了让它正常工作,我需要让流的位置为 0,而 JsonSerializer.SerializeObject 不这样做。它只是作用于一个流,当它完成时,流位置在 EOF。
我想做的是这样的:
public void SaveObject(object obj, string path, JsonSerializerSettings settings = null)
{
using (var jsonStream = new JsonStream(object, settings ?? _defaultSerializerSettings))
using (var gzipStream = new GZipStream(jsonStream))
{
var blob = GetCloudBlockBlob(path);
blob.UploadFromStream(gzipStream);
}
}
GZipStream
...想法是,直到某些东西拉取数据(在这种情况下,直到被方法拉取才压缩数据) ,序列化才开始,blob.UploadFromStream()
因此它保持低开销。它不需要是可搜索的流,它只需要按需读取。
我相信每个人都可以看到如果你从而System.IO.File.OpenRead()
不是new JsonStream(object obj)
. 虽然它变得有点复杂,因为 Json.NET 需要“向前看”并可能填充缓冲区,但他们让它与CryptoStream
and一起工作,并且工作得非常顺利GZipStream
。
有没有办法做到这一点,不会将对象的整个 JSON 表示加载到内存中,或者先将其假脱机到磁盘只是为了反刍?如果 CryptoStreams 可以做到,我们应该可以用 Json.NET 来做,而不需要大量的努力。我会想。