Маршалл несколько протобуф в файл - PullRequest
4 голосов
/ 18 августа 2010

Справочная информация:

Я использую protobuf от Google , и я хотел бы прочитать / записать несколько гигабайт данных, собранных с помощью protobuf, в файл с использованием C ++. Поскольку рекомендуется поддерживать размер каждого объекта protobuf менее 1 МБ, я подумал, что двоичный поток (показанный ниже), записанный в файл, будет работать. Каждое смещение содержит количество байтов до следующего смещения, пока не будет достигнут конец файла. Таким образом, каждый протобуф может оставаться меньше 1 МБ, и я могу соединить их вместе до глубины души.

[int32 offset]
[protobuf blob 1]
[int32 offset]
[protobuf blob 2]
...
[eof]

У меня есть реализация, которая работает на Github:

ЦСИ / glob.hpp
ЦСИ / glob.cpp
тест / readglob.cpp
тест / writeglob.cpp

Но я чувствую, что написал какой-то плохой код и был бы признателен за советы, как его улучшить. Таким образом,

Вопросы:

  • Я использую reinterpret_cast<char*> для чтения / записи 32-битных целых чисел в двоичный файл и из него fstream. Поскольку я использую protobuf, я предполагаю, что все машины имеют порядок байтов. Я также утверждаю, что int действительно 4 байта. Есть ли лучший способ чтения / записи 32-разрядного целого числа в двоичный файл fstream с учетом этих двух ограничивающих предположений?
  • При чтении из fstream я создаю временный буфер char фиксированной длины, чтобы затем я мог передать этот буфер фиксированной длины в библиотеку protobuf для декодирования с использованием ParseFromArray, так как ParseFromIstream будет потреблять весь поток. Я действительно предпочел бы просто сказать библиотеке, чтобы она читала не более следующих N байтов из fstream, но в protobuf такой функциональности, похоже, нет. Какой самый идиоматичный способ передать функцию длиной не более N байтов fstream? Или мой дизайн достаточно перевернут, чтобы я мог полностью рассмотреть другой подход?

Edit:

  • @ codymanix : Я работаю с char, поскольку istream::read требует массив char, если я не ошибаюсь. Я также не использую оператор извлечения >>, так как я прочитал, что это плохая форма для использования с двоичными потоками. Или этот последний совет фальшивый?
  • @ Мартин Йорк : Удалено new / delete в пользу std::vector<char>. glob.cpp обновлено. Спасибо!

1 Ответ

2 голосов
/ 18 августа 2010

Не используйте new [] / delete [].

Вместо этого мы используем std :: vector, поскольку освобождение гарантируется в случае исключений.

Не предполагайте, что чтениевернет все запрошенные вами байты.
Проверьте с помощью gcount (), чтобы убедиться, что вы получили то, что просили.

Вместо того, чтобы Glob реализовывал код для ввода и вывода в зависимости от переключателя вконструкторСкорее реализуйте два специализированных класса, таких как ifstream / ofstream.Это упростит как интерфейс, так и использование.

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