从二进制文件中读取结构化数据 - ?

时间:2010-07-14 04:49:14

标签: java parsing file-io

我知道文件结构,假设这个结构是这样的:

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

因此该文件包含此类记录的链。

用Java解析这样一个文件最优雅的方法是什么?

据说,我们可以定义一个整体长度的byte []数组并用InputStream读取它,但是如何将它的子元素转换成正确的整数值?

首先,java中的字节值是有符号的,在我们的例子中我们需要无符号值。 接下来,是否有一些有用的方法可以将字节的子数组(例如,从1到4的字节转换为正确的整数值)?

我肯定知道,有功能包&在Perl中解压缩,允许您将一个字节字符串表示为表达式,假设“VV”表示2个无符号长整数值。您定义了这样一个字符串,并将其作为参数提供给 pack unpack 函数,以及要打包/解包的字节。在Java / Apache库等中是否有这样的东西?

3 个答案:

答案 0 :(得分:3)

喜欢@Bryan Kyle的例子,但更短。我喜欢更短,但这并不意味着更清楚,你决定。 ;)注意:readByte()已签名,如果未使用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; 

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; 

答案 1 :(得分:1)

您可以查看此示例BinaryReader类,该类基于DataInputStream类。

答案 2 :(得分:1)

您应该可以使用DataInputStream执行此操作。我已经做了很多这样的开发已经有一段时间了,但我似乎记得的诀窍是,如果输入格式和语言数据类型之间存在阻抗不匹配,则需要逐字节构造数据。在这种情况下,看起来您需要这样做,因为数据结构具有奇怪的大小结构。

为您举例说明您可能需要做的第一条记录(我使用a,b和c作为记录的属性)

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();

显然,这个代码可以通过复合一些语句来收紧,但是你得到了一般的想法。您可能会注意到,对于每个要读取的属性,我必须使用比所需大的原语,因此没有任何溢出错误。作为参考,在Java中:

  • byte = 1 byte
  • 短= 16位,2字节
  • int = 32位,4个字节
  • long = 64位,8个字节