protocol protobuf google buffers protocol-buffers

protocol-buffers - buffers - google:: protobuf



Google Protocol Buffers-Almacenamiento de mensajes en un archivo (5)

De la documentación:

http://code.google.com/apis/protocolbuffers/docs/techniques.html#streaming

Transmisión de mensajes múltiples

Si desea escribir varios mensajes en un solo archivo o secuencia, depende de usted hacer un seguimiento de dónde termina un mensaje y comienza el siguiente. El formato de cable del búfer de protocolo no es autolimitado, por lo que los analizadores de búfer de protocolo no pueden determinar dónde termina un mensaje por sí solo. La forma más fácil de resolver este problema es escribir el tamaño de cada mensaje antes de escribir el mensaje en sí. Cuando vuelve a leer los mensajes, lee el tamaño, luego lee los bytes en un búfer separado y luego analiza desde ese búfer. (Si desea evitar copiar bytes en un búfer separado, verifique la clase CodedInputStream (tanto en C ++ como en Java) que se le puede indicar que limite las lecturas a un cierto número de bytes).

Estoy utilizando el búfer de protocolo de Google para serializar los datos del mercado de valores (es decir, campos de fecha y hora, oferta, campos de solicitud). Puedo almacenar un mensaje en un archivo y deserializarlo sin problema.

¿Cómo puedo almacenar varios mensajes en un solo archivo? No estoy seguro de cómo puedo separar los mensajes. Necesito poder agregar mensajes nuevos al archivo sobre la marcha.


Protobuf no incluye un terminador por registro externo, por lo que debe hacerlo usted mismo. El enfoque más simple es prefijar los datos con la longitud del registro que sigue. Personalmente, tiendo a utilizar el método de escribir un encabezado de cadena (para un número de campo arbitrario), luego la longitud como "varint" - esto significa que todo el documento es en sí mismo un protobuf válido, y podría consumirse como un objeto con un elemento "repetido", sin embargo, solo un marcador de longitud fija (generalmente de 32 bits little-endian) funcionaría igual de bien. Con cualquier almacenamiento de este tipo, es anexable como usted lo requiera.


Si está buscando una solución C ++, Kenton Varda envió un parche a protobuf en agosto de 2015 que agrega soporte para las llamadas writeDelimitedTo () y readDelimitedFrom () que serializarán / deserializarán una secuencia de mensajes proto a / desde un archivo de una manera eso es compatible con la versión de Java de estas llamadas. Lamentablemente, este parche aún no se ha aprobado, por lo que si desea la funcionalidad, deberá combinarla usted mismo.

Otra opción es que Google tiene código de lectura / escritura de archivos protobuf de código abierto a través de otros proyectos. La biblioteca or-tools , por ejemplo, contiene las clases RecordReader y RecordWriter que serializan / deserializan una secuencia de proto en un archivo.

Si desea versiones independientes de estas clases que casi no tienen dependencias externas, tengo una bifurcación de o-herramientas que contiene solo estas clases. Consulte: https://github.com/moof2k/recordio

Leer y escribir con estas clases es sencillo:

File* file = File::Open("proto.log", "w"); RecordWriter writer(file); writer.WriteProtocolMessage(msg1); writer.WriteProtocolMessage(msg2); ... writer.Close();


Una forma más fácil es codificar en base64 cada mensaje y almacenarlo como un registro por línea.


Recomendaría el uso de los writeDelimitedTo(OutputStream) y parseDelimitedFrom(InputStream) en los objetos de Message . writeDelimitedTo escribe la longitud del mensaje antes del mensaje en sí; parseDelimitedFrom luego usa esa longitud para leer solo un mensaje y no más. Esto permite que múltiples mensajes se escriban en un solo OutputStream para luego ser analizados por separado. Para obtener más información, consulte https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/MessageLite#writeDelimitedTo(java.io.OutputStream)