【发布时间】:2015-10-26 15:01:35
【问题描述】:
我需要归档每天用于构建报告的所有数据。我使用 gzip 压缩大部分数据,因为一些数据集可能非常大(10mb+)。我将每个单独的 protobuf 图写入文件。我还将一组固定的已知小对象类型列入白名单,并添加了一些代码来检测文件是否被 gzip 压缩,当我阅读它时。这是因为一个小文件,压缩后实际上可以比未压缩时更大。
不幸的是,仅仅由于数据的性质,我可能只有几个较大对象类型的元素,而白名单方法可能会出现问题。
有没有办法将一个对象写入一个流,并且只有当它达到一个阈值(比如 8kb),然后压缩它?我事先不知道对象的大小,有时我有一个带有IEnumerable<T> 的对象图,它的大小可能相当大。
编辑:
代码相当基本。我确实略过了我将其存储在filestream db 表中的事实。这对于实现目的来说并不重要。我删除了一些无关的代码。
public Task SerializeModel<T>(TransactionalDbContext dbConn, T Item, DateTime archiveDate, string name)
{
var continuation = (await dbConn
.QueryAsync<PathAndContext>(_getPathAndContext, new {archiveDate, model=name})
.ConfigureAwait(false))
.First();
var useGzip = !_whitelist.Contains(typeof(T));
using (var fs = new SqlFileStream(continuation.Path, continuation.Context, FileAccess.Write,
FileOptions.SequentialScan | FileOptions.Asynchronous, 64*1024))
using (var buffer = useGzip ? new GZipStream(fs, CompressionLevel.Optimal) : default(Stream))
{
_serializerModel.Serialize(stream ?? fs, item);
}
dbConn.Commit();
}
【问题讨论】:
-
尝试读取8k,如果数据少,则不压缩输出。否则,gzip 整个流,包括最初的 8k?您的具体问题是什么?
-
问题是我只有
T model并且我将它传递给protobuf.SerializeWithLengthPrefix,如果对象是1 字节或100mb 我不知道。 -
你插入一个输出流。该流实例必须缓冲 8k 数据,然后决定要做什么。然后它可以将解压缩或压缩的数据传递给另一个流。
-
@MichaelB 假设你可以做到这一点。在不知道流是否已压缩的情况下,您将如何处理反序列化?
-
这是最简单的部分。 Gzip 有一个很容易检测到的标头。
标签: c# protobuf-net gzipstream