C# 使用streams通过Json.NET创建BSON字节数组(用于文件格式)
我们需要与BSON等效的C# 使用streams通过Json.NET创建BSON字节数组(用于文件格式),c#,serialization,json.net,bson,C#,Serialization,Json.net,Bson,我们需要与BSON等效的 { "Header": { "SubHeader1": { "Name": "Bond", "License": 7 }, "SubHeader2": { "IsActive": true } }, "Payload": /* This will be a 40GB byte stream! */ } 但我们得
{
"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[]
,而不接受流。因为我们的有效负载将是10s的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库。因为我们很幸运,流只在末尾,所以我们现在使用BSON作为标题(足够小,可以容纳字节[]
),然后将其传递到标准流编写器,即表示法是:
{
"SubHeader1": {
"Name": "Bond",
"License": 7
},
"SubHeader2": {
"IsActive": true
}
} /* End of valid BSON */
// <= Our Stream is written here, raw byte stream, no BSON
{
“分目1”:{
“名称”:“债券”,
“许可证”:7
},
“分目2”:{
“IsActive”:正确
}
}/*有效BSON结束*/
//BsonWriter
仅在对象末尾写入数据(请参见BsonWriter.WriteEnd
)。看起来您必须复制到项目中并修改相当多的类(BsonWriter
、BsonBinaryWriter
、整个BsonToken
层次结构等),以便实现写流,因为它们不是为可扩展而设计的。该特性看起来非常有用,因此我建议修改库的代码并发出pull请求。顺便说一下,会有一些限制;一个要求是流需要支持告知其长度。对于BSON规范要求使用32位带符号整数来描述流长度(这会将最大“有效负载”大小限制为2 GB),您最初的解决方案是什么?@DuckMaestro:破解/扩展规范。我们计划将第一个uint32破解成一个uint64(4字节=>8字节),或将uint32长度=0指定为“忽略前4个字节,读取下一个8字节/uint64”。幸运的是,我们也不必走这条路,因为我们采用了另一种解决方案(见下文)。BSON很好,但在通用性方面仍有一些发展空间。另外,我们最终摆脱了BSON,并用ProtoBuf样式的头文件替换了它。使用Marc Gavell的实现,您可以使用类似于Serializer.DeserializeWithLengthPrefix(readSteam,PrefixStyle.Base128)的东西代码>。。。仅供参考
{
"SubHeader1": {
"Name": "Bond",
"License": 7
},
"SubHeader2": {
"IsActive": true
}
} /* End of valid BSON */
// <= Our Stream is written here, raw byte stream, no BSON