Нам нужны BSON эквивалент кИспользование потоков для создания массива BSON байт (для формата файла) с помощью Json.NET
{
"Header": {
"SubHeader1": {
"Name": "Bond",
"License": 7
},
"SubHeader2": {
"IsActive": true
}
},
"Payload": /* This will be a 40GB byte stream! */
}
Но что мы получаем:
As вы можете видеть, что полезная нагрузка появляется FIRST, а затем остальная часть заголовка!
Мы используем писателя BSON Json.NET (Bson.BsonWriter.WriteValue(byte[] value)
), но он принимает только byte[]
, а не Stream
. Так как наши полезные нагрузки будут 10s ГБ, мы должны использовать потоки, поэтому мы попытались обойти (код ниже), но это дает нам неправильный результат, показанный выше
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();
}
}
Это выглядит как классический случай нет синхронизация/не очистка буферов, несмотря на то, что мы действительно выпустили Flush для Json.NET, прежде чем писать полезную нагрузку в базовый поток.
Вопрос: Есть ли другой способ сделать это? Мы бы предпочли не отвалить от источника Json.NET (и исследовать его внутренние трубопроводы) или повторно изобрести колесо как-то ...
Детали: Опорные структуры классов (если вы хотите Репрографическим это)
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 и т. Д.), Чтобы реализовать потоки записи, поскольку они не предназначены для расширяемой. Эта функция выглядит весьма полезной, поэтому я предлагаю изменить код библиотеки и сделать запрос на перенос. Между прочим, будут некоторые ограничения; одним из требований является то, что потоку необходимо поддерживать его длину. – Athari
Каким будет ваше обходное решение в отношении спецификации BSON, требующей 32-разрядного целого числа со знаком для описания длины потока (что ограничило бы размер вашей полезной нагрузки до 2 ГБ)? – DuckMaestro
@DuckMaestro: взлом/расширение спецификации. Мы рассмотрели возможность взлома первого uint32 в uint64 (4 байта => 8 байтов) ИЛИ назначение особому значению uint32 length = 0 как «игнорировать первые 4 байта и читать следующие 8 байтов/uint64». К счастью, нам не пришлось идти по этому маршруту, так как мы приняли альтернативное решение (см. Ниже). BSON хорош, но все еще есть возможность расти для общности. – DeepSpace101