Проблема буферов протокола, множественные сериализации в двоичный файл - PullRequest
4 голосов
/ 01 декабря 2011

Я получаю странное поведение из двоичного файла protobuf io.Я предварительно обрабатываю текстовый корпус в промежуточный файл protobuf.Мой класс сериализации выглядит следующим образом:

  class pb_session_printer
  {
  public:
    pb_session_printer(std::string & filename)
      : out(filename.c_str(), std::fstream::out | std::fstream::trunc | 
                              std::fstream|binary)
      {}

    void print_batch(std::vector<session> & pb_sv)
    {
      boost::lock_guard<boost::mutex> lock(m);

      BOOST_FOREACH(session & s, pb_sv)
      {
        std::cout << out.tellg() << ":";
        s.SerializeToOstream(&out);
        out.flush();
        std::cout << s.session_id() << ":" << s.action_size() << std::endl;
      }
      exit(0);
    }

    std::fstream out;
    boost::mutex m;
  };

Фрагмент вывода выглядит следующим образом:

0:0:8
132:1:8
227:2:6
303:3:6
381:4:19
849:5:9
1028:6:2
1048:7:18
1333:8:28
2473:9:24

Первое поле показывает, что сериализация происходит как обычно.

Когда я запускаю свою загрузочную программу:

int main()
{
  std::fstream in_file("out_file", std::fstream::in | std::ios::binary);
  session s;

  std::cout << in_file.tellg() << std::endl;
  s.ParseFromIstream(&in_file);
  std::cout << in_file.tellg() << std::endl;
  std::cout << s.session_id() << std::endl;

  s.ParseFromIstream(&in_file);
}

Я получаю:

0
-1
111
libprotobuf ERROR google/protobuf/message_lite.cc:123] Can't parse message of type 
"session" because it is missing required fields: session_id

session_id: 111 - это запись в конце потока, я явно нене понимаю семантику двоичных объектов библиотеки.Пожалуйста, помогите.

Ответы [ 2 ]

4 голосов
/ 01 декабря 2011

Если вы пишете несколько протобуферов в одном файле, вам нужно будет записать размер protobuf + protobuffer и прочитать их отдельно (поэтому без ParseFromIstream, как упоминалось в Cat Plus Plus). Когда вы прочитали протобуфер, вы можете проанализировать его с помощью ParseFromArray.

Ваш файл будет выглядеть по размеру (пробелы только для удобства чтения):

Размер протобуф Размер протобуф Размер протобуф и т. Д.

3 голосов
/ 01 декабря 2011

Message::ParseFromIstream задокументировано для использования всего ввода.Поскольку вы сериализуете последовательность сообщений одного типа, вы можете просто создать новое сообщение с полем repeated этого типа и работать с ним.

...