Хранение нескольких сообщений в одном двоичном файле буфера протокола - PullRequest
5 голосов
/ 07 апреля 2011

У меня есть повторяющиеся сообщения, которые я хочу сохранить в одном файле. В настоящее время я должен обернуть это повторяющееся сообщение в другое сообщение. Есть ли способ обойти это?

package foo;

message Box {
  required int32 tl_x = 1;
  required int32 tl_y = 2;
  required int32 w = 3;
  required int32 h = 4;
}

message Boxes {
  repeated Box boxes = 1;
}

Ответы [ 3 ]

12 голосов
/ 08 апреля 2011

Вот что говорит «Методы» в документации по протоколу буфера о повторяющихся сообщениях:

Если вы хотите записать несколько сообщений в один файл или поток, этодо вас, чтобы отслеживать, где заканчивается одно сообщение и начинается следующее.Формат протокола Protocol Buffer не является саморазграничением, поэтому синтаксические анализаторы буфера протокола не могут самостоятельно определить, где заканчивается сообщение.Самый простой способ решить эту проблему - записать размер каждого сообщения перед тем, как написать само сообщение.Когда вы читаете сообщения обратно, вы читаете размер, затем читаете байты в отдельный буфер, а затем анализируете этот буфер.(Если вы хотите избежать копирования байтов в отдельный буфер, проверьте класс CodedInputStream (как на C ++, так и на Java), который может быть ограничен чтением определенным количеством байтов.)

Естьтакже традиционный способ реализации этого в C ++ и Java.Посмотрите на этот поток переполнения стека для деталей: Существуют ли эквиваленты C ++ для функций ввода-вывода, разделенных буфером протокола, в Java?

6 голосов
/ 08 апреля 2011

Protobuf не поддерживает эту функцию. Его можно использовать только для сериализации одного сообщения, но это сериализованное сообщение не содержит информации о его типе (поле или ящики) и длине. Поэтому, если вы хотите сохранить несколько сообщений, вы должны также указать тип и длину сообщения. Алгоритм записи (на псевдо-языке) может выглядеть так:

for every message {
    write(type_of_message) // 1 byte long
    write(length_of_serialized_message) // 4 bytes long
    write(serialized_message)
}

Алгоритм загрузки:

while(end_of_file) {

    type = read(1) // 1 byte
    length = read(4) // 4 bytes
    buffer = read(length)
    switch (type) {
      case 1:
         deserialise_message_1(buffer)
      case 2:
         deserialise_message_2(buffer)
    }
}
1 голос
/ 08 апреля 2011

В Java вы можете использовать сообщения с разделителями. Для C ++ см. Существуют ли эквиваленты C ++ для функций ввода-вывода, разделенных буфером протокола, в Java?

В основном в C ++ в соответствии с вышеприведенным

const unsigned bufLength = 256;
unsigned char buffer[bufLength];
Message protoMessage;

google::protobuf::io::ArrayOutputStream arrayOutput(buffer, bufLength);
google::protobuf::io::CodedOutputStream codedOutput(&arrayOutput);

codedOutput.WriteLittleEndian32(protoMessage.ByteSize());
protoMessage.SerializeToCodedStream(&codedOutput);

и python, вам нужно было бы разобраться

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...