2010-04-19 23 views
13

Necesito analizar algunos archivos binarios simples. (Los archivos contienen n entradas que consta de varios enteros con y sin signo de diferentes tamaños, etc.)Análisis de datos binarios con scala

En el momento en que realizo el análisis "a mano". ¿Alguien conoce una biblioteca que ayuda a hacer este tipo de análisis?

Editar: "A mano" significa que obtengo el byte de datos Byte, ordeno en el orden correcto y lo convierto en un int/byte, etc. También algunos de los datos no están firmados.

Respuesta

7

He usado la biblioteca sbinary antes y es muy agradable. La documentación es un poco escasa, pero le sugiero que primero vea el viejo wiki page ya que eso le da un punto de partida. Luego, revise las especificaciones de prueba, ya que eso le da algunos ejemplos muy buenos.

El principal beneficio de sbinary es que le ofrece una forma de describir el formato de conexión de cada objeto como un objeto de Formato. A continuación, puede encapsular esos tipos de formato en un objeto Format de nivel superior y Scala hace todo el trabajo pesado de buscar ese tipo siempre que lo haya incluido en el alcance actual como un objeto implícito.

Como digo a continuación, ahora recomendaría que la gente use scodec en lugar de sbinary. Como un ejemplo de cómo utilizar scodec, voy a implementar cómo leer una representación binaria en la memoria de la siguiente estructura C:

struct ST 
{ 
    long long ll; // @ 0 
    int i;  // @ 8 
    short s;  // @ 12 
    char ch1;  // @ 14 
    char ch2;  // @ 15 
} ST; 

Una clase caso Scala juego sería:

case class ST(ll: Long, i: Int, s: Short, ch1: String, ch2: String) 

I Me estoy haciendo las cosas un poco más fáciles al decir que estamos almacenando cadenas en lugar de caracteres y diré que son caracteres UTF-8 en la estructura. Tampoco estoy tratando con los detalles endian o el tamaño real de los tipos largo e int en esta arquitectura y simplemente suponiendo que son 64 y 32 respectivamente.

Los analizadores de Scodec generalmente usan combinadores para construir analizadores de nivel superior de los de nivel inferior. Entonces para abajo, definiremos un analizador sintáctico que combina un valor de 8 bytes, un valor de 4 bytes, un valor de 2 bytes, un valor de 1 byte y un valor de 1 byte más.El retorno de esta combinación es un códec de tupla:

val myCodec: Codec[Long ~ Int ~ Short ~ String ~ String] = 
    int64 ~ int32 ~ short16 ~ fixedSizeBits(8L, utf8) ~ fixedSizeBits(8L, utf8) 

Entonces podemos transformar esto en la clase caso ST llamando a la función xmap en él que tiene dos funciones, una para activar el códec de tuplas en el tipo de destino y otra función para tomar el tipo de destino y convertirla en la forma de tupla:

val stCodec: Codec[ST] = myCodec.xmap[ST]({case ll ~ i ~ s ~ ch1 ~ ch2 => ST(ll, i, s, ch1, ch2)}, st => st.ll ~ st.i ~ st.s ~ st.ch1 ~ st.ch2) 

Ahora, puede utilizar el códec de este modo:

stCodec.encode(ST(1L, 2, 3.shortValue, "H", "I")) 
res0: scodec.Attempt[scodec.bits.BitVector] = Successful(BitVector(128 bits, 0x00000000000000010000000200034849)) 

res0.flatMap(stCodec.decode) 
=> res1: scodec.Attempt[scodec.DecodeResult[ST]] = Successful(DecodeResult(ST(1,2,3,H,I),BitVector(empty))) 

Le animo a que mire los Scaladocs y no a la Guía ya que hay muchos más detalles en los Scaladocs. La guía es un buen comienzo desde lo básico, pero no entra mucho en la composición, pero los Scaladocs lo cubren bastante bien.

+0

En caso de que alguien vea esto, recomendaría http://scodec.org ahora. Los mismos beneficios que sbinary pero mejor soporte y más capacidades. – Aaron

+0

Todavía no tengo idea de cómo usar las bibliotecas 'sbinary' o' scodec' para analizar un protocolo binario definido en otra parte como una secuencia de estructuras C incluso después de pasar por las documentaciones respectivas. ¿Podría elaborar, preferiblemente con un fragmento de código? – nodakai

+0

Acabo de agregar un ejemplo de análisis scodec para una estructura C-style. ¡Espero que ayude! – Aaron

4

No sé lo que quiere decir con "a mano", pero usando un simple DataInputStream (apidoc here) es bastante clara y concisa:

val dis = new DataInputStream(yourSource) 

dis.readFloat() 
dis.readDouble() 
dis.readInt() 
// and so on 

tomado de otro SO question: http://preon.sourceforge.net/, debe ser un marco para hacer codificaciones/decodificaciones binarias ... vea si tiene las capacidades que necesita

+1

¿Qué pasa con endianess? ¿Qué pasa con las cuerdas pascuales (byte para el tamaño y luego la cadena en ascii)? Creo que está buscando algo como 'struct.pack',' struct.unpack' de python. –

+0

Nadie quiere hacerlo para obtener un ejemplo del mundo real como [archivo BMP] (https://en.wikipedia.org/wiki/BMP_file_format#DIB_header_.28bitmap_information_header.29) especialmente cuando no se utilizan todos los miembros de datos. – nodakai

4

Scala en sí no tiene una biblioteca de entrada de datos binarios, pero el paquete java.nio hace un trabajo decente. No maneja explícitamente los datos sin firmar, tampoco lo hace Java, por lo que necesita averiguar cómo desea administrarlo, pero sí cuenta con métodos convenientes de "obtención" que tienen en cuenta el orden de los bytes.

1

Si está buscando una solución basada en Java, entonces descaradamente enchufaré Preon. Simplemente haga una anotación en la estructura de datos Java de la memoria, y pida a Preon un códec, y listo.

+0

https://github.com/preon/preon ¿Puedo usarlo en un archivo '.scala', o necesito un archivo' .java'? – nodakai

1

Byteme es una biblioteca de combinadores de analizadores para hacer binarios. Puede intentar usarlo para sus tareas.