【发布时间】:2013-06-15 00:42:52
【问题描述】:
我们需要 BSON 等效 来
{
"Header": {
"SubHeader1": {
"Name": "Bond",
"License": 7
},
"SubHeader2": {
"IsActive": true
}
},
"Payload": /* This will be a 40GB byte stream! */
}
但我们得到的是:
如您所见,有效载荷首先出现,然后是头部的其余部分!
我们正在使用 Json.NET 的 BSON 编写器 (Bson.BsonWriter.WriteValue(byte[] value)),但它只接受实际的 byte[],而不是 Stream。由于我们的有效负载将是 10 GB,我们必须使用流,所以我们尝试解决(下面的代码),但这给了我们上面显示的错误结果
public void Expt()
{
// Just some structure classes, defined below
var fileStruct = new FileStructure();
using (Stream outputSt = new FileStream("TestBinary.bson", FileMode.Create))
{
var serializer = new JsonSerializer();
var bw = new BsonWriter(outputSt);
// Start
bw.WriteStartObject();
// Write header
bw.WritePropertyName("Header");
serializer.Serialize(bw, fileStruct.Header);
// Write payload
bw.WritePropertyName("Payload");
bw.Flush(); // <== flush !
// In reality we 40GB into the stream, dummy example for now
byte[] dummyPayload = Encoding.UTF8.GetBytes("This will be a 40GB byte stream!");
outputSt.Write(dummyPayload, 0, dummyPayload.Length);
// End
bw.WriteEndObject();
}
}
这看起来像是没有同步/不刷新缓冲区的经典案例,尽管我们实际上在将有效负载写入底层流之前向 Json.NET 发出了 Flush。
问题:还有其他方法吗?我们宁愿不分叉 Json.NET 的源代码(并探索它的内部管道)或以某种方式重新发明轮子... p>
详情:支持的结构类是(如果你想重现这个)
public class FileStructure
{
public TopHeader Header { get; set; }
public byte[] Payload { get; set; }
public FileStructure()
{
Header = new TopHeader
{
SubHeader1 = new SubHeader1 {Name = "Bond", License = 007},
SubHeader2 = new SubHeader2 {IsActive = true}
};
}
}
public class TopHeader
{
public SubHeader1 SubHeader1 { get; set; }
public SubHeader2 SubHeader2 { get; set; }
}
public class SubHeader1
{
public string Name { get; set; }
public int License { get; set; }
}
public class SubHeader2
{
public bool IsActive { get; set; }
}
【问题讨论】:
-
BsonWriter仅在对象末尾写入数据(请参阅BsonWriter.WriteEnd)。看起来您必须复制到您的项目中并修改相当多的类(BsonWriter、BsonBinaryWriter、整个BsonToken层次结构等)才能实现写入流,因为它们并非旨在可扩展的。该功能看起来非常有用,因此我建议修改库的代码并发出拉取请求。顺便说一下,会有一些限制;一个要求是流需要支持告诉它的长度。 -
关于 BSON 规范要求 32 位有符号整数来描述流长度(这会将您的最大“有效负载”大小限制为 2 GB),您最初的解决方法是什么?
-
@DuckMaestro:黑客/扩展规范。我们考虑将第一个 uint32 破解为 uint64(4 字节 = > 8 字节)或为 uint32 长度 = 0 分配特殊含义,如“忽略第一个 4 字节并读取接下来的 8 字节/uint64”。幸运的是,我们也不必走那条路,因为我们采用了替代解决方案(见下文)。 BSON 不错,但在通用性方面仍有一些发展空间。
标签: c# serialization json.net bson