2010-07-14 12 views
5

sé la estructura de archivos, supongamos que esta estructura es la siguiente:Leer datos estructurados del archivo binario -?

[3-bytes long int],[1-byte long unsigned integer],[4-bytes long unsigned integer] 

Así que el archivo contiene cadenas de tales registros.

¿Cuál es la forma más elegante de analizar un archivo como este en Java?

Supuestamente, podemos definir una matriz byte [] de longitud total y leerla con InputStream, pero ¿cómo convertir sus subelementos en valores enteros correctos?

Primero, el valor de byte en java está firmado, necesitamos el valor sin signo en nuestro caso. Lo siguiente, ¿hay métodos útiles que permitan convertir una sub-matriz de bytes, por ejemplo, bytes de 1-st a 4-th en un valor entero correcto?

Sé con certeza, hay funciones paquete & desempaquetar en Perl, que le permiten representar una cadena de bytes como una expresión, digamos "VV" significa 2 valores enteros largos sin signo. Defina una cadena de este tipo y bríndela como argumento a un paquete o desempaquete las funciones, junto con los bytes que se empaquetarán/desempaquetarán. ¿Hay cosas en Java/Apache libs, etc.?

+0

posible duplicado de [Mejor manera de leer archivos binarios estructurados con Java] (http://stackoverflow.com/questions/277944/best-way-to-read-structured -binary-files-with-java) –

Respuesta

1

Debería poder hacer esto usando un DataInputStream. Ha pasado un tiempo desde que hice mucho desarrollo como este, pero el truco que parece recordar es que si hay un desajuste de impedancia entre su formato de entrada y los tipos de datos del idioma, necesitará construir los datos byte a byte . En este caso, parece que tendrá que hacer eso porque la estructura de datos tiene estructuras de tamaño extraño.

Para dar un ejemplo de leer el primer registro puede que tenga que hacer algo como esto (estoy usando A, B, y C para los atributos del registro)

DataInputStream dis = ... 

int a = 0; 
a = dis.readByte(); 
a = a << 8;   
a = a | dis.readByte(); 
a = a << 8; 
a = a | dis.readByte(); 

short b = 0; 
b = dis.readByte(); 

long c = 0; 
c = dis.readByte(); 
c = c << 8; 
c = c | dis.readByte(); 
c = c << 8; 
c = c | dis.readByte(); 
c = c << 8; 
c = c | dis.readByte(); 

Obviamente, esto el código se puede reforzar compilando algunas de las declaraciones, pero se obtiene la idea general. Lo que podría notar es que para cada uno de los atributos que se leen, tengo que usar una primitiva que es más grande que la necesaria para que no haya ningún error de desbordamiento. Como referencia, en Java:

  • byte = 1 byte
  • cortos = 16 bits, 2 bytes
  • int = 32 bits, 4 bytes
  • largo = 64 bits, 8 bytes
3

Me gusta el ejemplo de @Bryan Kyle pero más corto. Me gusta más corto, pero eso no quiere decir más claro, tú decides. ;) Nota: readByte() está firmado y tendrá resultados inesperados si no está enmascarado con 0xFF.

DataInputStream dis = ... 

// assuming BIG_ENDIAN format 
int a = dis.read() << 16 | dis.read() << 8 | dis.read(); 
short b = (short) dis.read(); 
long c = dis.readInt() & 0xFFFFFFFFL; 

o

ByteBuffer bb = 
bb.position(a_random_postion); 
int a = (bb.get() & 0xFF) << 16 | (bb.get() & 0xFF) << 8 | (bb.get() & 0xFF); 
short b = (short) (bb.get() & 0xFF); 
long c = bb.readInt() & 0xFFFFFFFFL; 
Cuestiones relacionadas