Я пытаюсь читать / пишут несколько Буферных сообщений Протокола из файлов, и в C++ и в Java. Google предлагает писать префиксы длины перед сообщениями, но нет никакого способа сделать это по умолчанию (что я видел).
Однако API Java в версии 2.1.0 получил ряд "Разграниченных" функций ввода-вывода, которые, по-видимому, делают то задание:
parseDelimitedFrom
mergeDelimitedFrom
writeDelimitedTo
Есть ли эквиваленты C++? И в противном случае каков проводной формат для префиксов размера Java присоединения API, таким образом, я могу проанализировать те сообщения в C++?
Они теперь существуют в google/protobuf/util/delimited_message_util.h
с v3.3.0.
Я решил ту же проблему, используя CodedOutputStream/ArrayOutputStream для записи сообщения (с размером) и CodedInputStream/ArrayInputStream для чтения сообщения (с размером).
Например, следующий псевдокод записывает размер сообщения, за которым следует сообщение:
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);
При записи вы также должны проверить, что ваш буфер достаточно велик, чтобы вместить сообщение (включая размер). А при чтении вы должны проверить, что ваш буфер содержит целое сообщение (включая размер).
Определенно было бы удобно, если бы в C++ API добавили методы удобства, аналогичные тем, которые предоставляет Java API.
Итак, я не смог найти функции верхнего уровня C++, реализующие то, что мне нужно, но некоторые поиски в справке Java API привели к следующему, внутри интерфейса MessageLite:
void writeDelimitedTo(OutputStream output)
/* Like writeTo(OutputStream), but writes the size of
the message as a varint before writing the data. */
Итак, префикс размера в Java - это (Protocol Buffers) varint!
Вооруженный этой информацией, я пошел копаться в C++ API и нашел заголовок CodedStream, в котором есть следующее:
bool CodedInputStream::ReadVarint32(uint32 * value)
void CodedOutputStream::WriteVarint32(uint32 value)
Используя это, я должен быть в состоянии создать свои собственные C++ функции, которые выполняют эту работу.
Они действительно должны добавить это в основной Message API; это недостающая функциональность, учитывая, что Java имеет это, как и отличный порт Марка Грейвелла protobuf-net C# (через SerializeWithLengthPrefix и DeserializeWithLengthPrefix).
Вы можете использовать getline для чтения строки из потока, используя указанный разделитель:
istream& getline ( istream& is, string& str, char delim );
(определено в заголовке)