C# 使用streams通过Json.NET创建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! */ } 但我们得

我们需要与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[]
,而不接受
流。因为我们的有效负载将是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