2008-10-24 16 views
106

¿Es posible serializar y deserializar una clase en C++?¿Es posible serializar y deserializar una clase en C++?

He estado utilizando Java durante 3 años, y la serialización/deserialización es bastante trivial en ese idioma. ¿Tiene C++ características similares? ¿Hay bibliotecas nativas que manejan la serialización?

Un ejemplo sería útil.

+2

no estoy seguro de lo que quiere decir con "native", ¿se refiere a native C++ (like Boost.Serialization)? ¿Quiere decir que solo usa la biblioteca estándar de C++? ¿Te refieres a algo más? – jwfearn

+1

me refiero a "no una biblioteca de software externa". Y lo siento, mi inglés no está muy bien: S. Soy de Argentina –

+2

No hay forma nativa de serializar un objeto (aún puedes volcar los datos binarios desde un POD, pero no obtendrás lo que deseas). Aun así, Boost, si bien no es una "biblioteca interna", es la primera biblioteca externa que debe considerar agregar a su compilador. Boost es de calidad STL (es decir, Top Gun C++) – paercebal

Respuesta

80

La biblioteca Boost::serialization lo maneja con elegancia. Lo he usado en varios proyectos. Hay un programa de ejemplo que muestra cómo usarlo, here.

La única manera nativa de hacerlo es utilizar secuencias. Eso es esencialmente todo lo que hace la biblioteca Boost::serialization, amplía el método de flujo al configurar un marco para escribir objetos en un formato de texto y leerlos desde el mismo formato.

Para tipos incorporados, o sus propios tipos con operator<< y operator>> correctamente definidos, eso es bastante simple; ver the C++ FAQ Lite para más información.

+0

Me parece que boost :: serialization requiere que el llamante realice un seguimiento del orden en que se escriben y leen los objetos. ¿Es eso correcto? Entonces, si hay un cambio en el orden en que se escriben dos campos entre las versiones de un programa, entonces tenemos una incompatibilidad. ¿Es esto correcto? –

+0

Creo que ese es el caso, sí. –

+0

La serialización de Boost me falló cuando intenté serializar usando la aplicación de 32 bits y la deserialización usando la versión de 64 bits. –

15

Boost es una buena sugerencia. Pero si desea hacer su propio, no es tan difícil.

Básicamente, solo necesita una forma de crear un gráfico de objetos y luego darles salida a algún formato de almacenamiento estructurado (JSON, XML, YAML, lo que sea). Construir el gráfico es tan simple como utilizar un algoritmo decente de objeto recursivo y luego generar todos los objetos marcados.

Escribí un artículo que describe un sistema de serialización rudimentario (pero aún poderoso). Puede encontrarlo interesante: Using SQLite as an On-disk File Format, Part 2.

9

En cuanto a las bibliotecas "incorporadas", << y >> se han reservado específicamente para la serialización.

Debe sobrescribir << para enviar su objeto a algún contexto de serialización (generalmente un iostream) y >> para leer datos de ese contexto. Cada objeto es responsable de generar sus objetos secundarios agregados.

Este método funciona bien siempre que su gráfico de objetos no contenga ciclos.

Si lo hace, entonces tendrá que usar una biblioteca para manejar esos ciclos.

+3

Seguramente, eso no puede ser correcto ... los operadores '<<' implementados se utilizan para imprimir representaciones de texto de objetos legibles por el ser humano, que a menudo no es lo que usted quiere para la serialización. – einpoklum

+0

@einpoklum En lugar de definir '<<' para el genérico 'ostream', intente definirlo para una secuencia de archivos. – Carcigenicate

+1

@Carcigenicate: un archivo de registro que toma texto legible para humanos es una secuencia de archivos. – einpoklum

12

Recomiendo Google protocol buffers. Tuve la oportunidad de probar la biblioteca en un nuevo proyecto y es notablemente fácil de usar. La biblioteca está muy optimizada para el rendimiento.

Protobuf es diferente a otras soluciones de serialización mencionadas aquí en el sentido de que no serializa sus objetos, sino que genera código para objetos que son serializados de acuerdo con sus especificaciones.

+2

¿Ha tenido experiencia serializando objetos de aproximadamente 10-50MB de tamaño con esto? La documentación parece decir que los búferes de protocolo son más adecuados para objetos de un MB de tamaño. –

2

sugiero mirar en fábricas abstractas que se utiliza a menudo como una base para la serialización

he respondido en otro SO pregunta sobre fábricas de C++. Consulte there si una fábrica flexible es de su interés. Intento describir una antigua forma de ET ++ para usar macros, que me ha funcionado muy bien.

ET++ fue un proyecto para portar MacApp antiguo a C++ y X11. En el esfuerzo de ello Eric Gamma, etc. comenzó a pensar en Patrones de diseño. ET ++ contenía formas automáticas para la serialización y la introspección en tiempo de ejecución.

4

puede comprobar el protocolo amef, un ejemplo de codificación C++ en AMEF sería como,

//Create a new AMEF object 
    AMEFObject *object = new AMEFObject(); 

    //Add a child string object 
    object->addPacket("This is the Automated Message Exchange Format Object property!!","adasd"); 

    //Add a child integer object 
    object->addPacket(21213); 

    //Add a child boolean object 
    object->addPacket(true); 

    AMEFObject *object2 = new AMEFObject(); 
    string j = "This is the property of a nested Automated Message Exchange Format Object"; 
    object2->addPacket(j); 
    object2->addPacket(134123); 
    object2->addPacket(false); 

    //Add a child character object 
    object2->addPacket('d'); 

    //Add a child AMEF Object 
    object->addPacket(object2); 

    //Encode the AMEF obejct 
    string str = new AMEFEncoder()->encode(object,false); 

decodificación en Java sería como,

string arr = amef encoded byte array value; 
    AMEFDecoder decoder = new AMEFDecoder() 
    AMEFObject object1 = AMEFDecoder.decode(arr,true); 

la implementación del protocolo tiene codecs para tanto C++ y Java, la parte interesante es que puede retener la representación de clases de objetos en forma de pares de valores de nombres, Requirí un protocolo similar en mi último proyecto, cuando por casualidad tropecé con este protocolo, en realidad tuve mod ified la biblioteca base según mis requisitos. Espero que esto te ayude.

11

Boost::serialization es una gran opción, pero he encontrado un nuevo proyecto: Cereal que me parece mucho más elegante! Recomiendo investigarlo.

38

Me doy cuenta de que esta es una publicación anterior, pero es una de las primeras que aparece al buscar c++ serialization.

Animo a cualquiera que tenga acceso a C++ 11 a echar un vistazo a cereal, una biblioteca de sólo encabezado C++ 11 para serialización que admite binarios, JSON y XML de fábrica. el cereal fue diseñado para ser fácil de extender y usar y tiene una sintaxis similar a Boost.

+4

Lo bueno de los cereales es que, a diferencia del impulso, tiene metadatos mínimos (casi ninguno). boost :: la serialización se vuelve realmente molesta cuando cada vez que abre un archivo, escribe su versión de lib en la secuencia, lo que hace que anexar un archivo sea imposible. – CyberSnoopy

+0

@CyberSnoopy: hay un indicador para suprimir esta característica cuando se crea un archivo; por supuesto, debe recordarlo al leer el archivo también. –

3

Sweet Persist es otro.

Es posible serializar desde y hacia las secuencias en XML, JSON, Lua y formatos binarios.

0

Si desea simple y mejor rendimiento y no se preocupan por la compatibilidad de datos hacia atrás, tratar HPS, es ligero, mucho más rápido que la del refuerzo, etc., y mucho más fácil de usar que Protobuf, etc.

Ejemplo:

std::vector<int> data({22, 333, -4444}); 
std::string serialized = hps::serialize_to_string(data); 
auto parsed = hps::parse_from_string<std::vector<int>>(serialized); 
Cuestiones relacionadas