Serializar objetos Java en formato binario

En tutoriales anteriores aprendimos como serializar objetos Java en formato JSON ya sea para enviarlos por la red o guardarlos en un archivo, para esta ocasión vamos a estudiar la librería msg-pack la cual nos permitirá serializar objetos Java o tipos primitivos en formato binario, al utilizar un archivo binario la lectura y la escritura es mucho más rápida, además el tamaño del archivo se reduce en comparación a un archivo que almacena JSON en formato texto plano.

msgpack

Para utilizar esta librería en nuestro tutorial haremos uso de Maven, agregamos la siguiente dependencia a nuestro proyecto demostrativo:

<dependency>
    <groupId>org.msgpack</groupId>
    <artifactId>msgpack-core</artifactId>
    <version>0.8.14</version>
</dependency>

Guardar datos primitivos

En este primer ejemplo veamos como podemos guardar los tipos primitivos usados por Java en formato binario, nos referimos a los tipos: int, boolean, double, etc.

// crear objeto MessagePacker (encoder) 
MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();

// codificar los tipos primitivos
packer.packBoolean(true);
packer.packShort((short) 34);
packer.packInt(1);
packer.packLong(33000000000L);
packer.packFloat(0.1f);
packer.packDouble(3.14159263);
packer.packByte((byte) 0x80);

// obtener el arreglo de bytes
byte[] out = packer.toByteArray();

// crear objeto MessageUnpaker (decoder)
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(out);

// decodificar los datos primitivos 
System.out.println("boolean: " + unpacker.unpackBoolean());
System.out.println("short:   " + unpacker.unpackShort());
System.out.println("int      " + unpacker.unpackInt());
System.out.println("long:    " + unpacker.unpackLong());

Como se puede observar para codificar los datos primero debemos obtener una instancia MessageBufferPacker luego utilizar los respectivos métodos packXXX() para serializar los respectivos datos, usando el método toByteArray() obtenemos el arreglo de byte que representa nuestros datos serializados en formato binario.

De un modo similar pero al inverso, cuando deseemos leer los datos a partir de un arreglo de byte, usamos una instancia MessageUnpacker igual utilizaremos los métodos unpackXXX() para obtener los datos Java respectivos.

Serializar String y Arreglos

Podemos almacenar datos de tipo String, Arreglos y Map de manera similar, solo debemos tomar ciertas consideraciones, veamos un ejemplo:

// pack String
packer.packString("hello message pack!");

// pack arrays
int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
packer.packArrayHeader(arr.length);
for (int v : arr) {
    packer.packInt(v);
}

Primero vemos como guardar una cadena de texto, luego un arreglo de tipo entero, nótese que usamos el método packArrayHeader(int) para indicar la cantidad de elementos del arreglo, luego introducimos los elementos a través del método packInt(int).

// pack Map, indicamos la cantidad de elementos
packer.packMapHeader(2);

// primer elemento del Map
packer.packString("apple"); // clave
packer.packInt(1);          // valor

// segundo elemento del Map
packer.packString("banana"); // clave
packer.packInt(2);           // valor

De modo similar a un arreglo podemos también guardar un Map o arreglo asociativo, primero indicamos el la cantidad de elementos, luego por cada elemento introducimos primero la clave y luego el valor respectivo.

Cuando deseemos leer los datos recordamos primero leer la cantidad de elementos y luego usar los respectivos métodos unpackXXX() para obtener los valores deseados.

Usar con Jackson

En tutoriales anteriores vimos la librería Jackson que nos permite serializar objetos en formato JSON de manera sencilla, msgpack nos proporciona la librería jackson-dataformat-msgpack la cual nos permitirá seguir usando Jackson pero serializando los datos en formato binario.

<dependency>
    <groupId>org.msgpack</groupId>
    <artifactId>jackson-dataformat-msgpack</artifactId>
    <version>0.8.14</version>
</dependency>

Luego de agregar la dependencia solo hacemos lo siguiente:

// objeto a serializar
Person p = new Person();
p.setAge(15);
p.setGender(true);
p.setName("Tutorial");

// archivo binario para crear 
File file = new File("binary.dat");

// jackson ObjectMapper
ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());

// escribir el objeto Person
mapper.writeValue(file, p);

// leer el objeto Person
Person person = mapper.readValue(file, Person.class);

Puedes ver que el modo para utilizar Jackson es muy similar al visto en el respectivo tutorial, lo único nuevo que añadimos es el objeto MessagePackFactory() puedes verificar que el archivo binary.dat se ha creado, este contiene el objeto Person serializado en formato binario.

Descargar código: serializar-binario.zip

Comentarios

Temas relacionados

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Manipular pixeles OpenCV Python

Detección de contornos con OpenCV Python

Conociendo la clase cv::Mat de OpenCV