【问题标题】:Java: parsing unsigned binary dataJava:解析无符号二进制数据
【发布时间】:2014-01-31 02:50:31
【问题描述】:

我有一个定义明确的二进制数据,我想为它编写 Java API。
文件格式是这样的

File Signature     char[4]               4 bytes 
File Source ID     unsigned short        2 bytes
Header Size        unsigned long         4 bytes
Max                double                8 bytes

我正在使用DataInputStream 来解析数据。 char 很容易解析,没问题。但是unsigned 无法正确解析。
我知道Java 没有无符号数。我该如何转换它? (请以 unsigned long 为例)。

编辑

这是我写的代码:

File file = new File("lidar.las");

DataInputStream in= new DataInputStream(new FileInputStream(file));

in.skipBytes(6);

long read = (long) (in.readInt() & 0xFFFFFFFFL);

System.out.println("read " + read);


输出是

阅读 3288596480

我的预期数字是 1220 .我不知道写这个二进制记录的代码,可能是c。我想要的只是编写一个 Java 版本来读取数据。

已解决
我不确定我能否回答我自己的问题。哈哈
无论如何,这是解决方案。

private static int getSignedInt( final int unsignedInt ){

    ByteBuffer bb=ByteBuffer.allocate(1024*4);

    bb.putInt(unsignedInt).flip();

    int result =bb.order(ByteOrder.LITTLE_ENDIAN).getInt();
    bb.clear();

    return  result;
}

【问题讨论】:

  • 您需要对它们进行某种数学运算吗?你需要一个 8 字节的无符号整数吗?显而易见的答案是将它们读入有符号整数,例如您的 4 字节无符号长整数适合 Java 长整数。
  • unsigned long 在任何现代系统上都不会是 4 个字节。除此之外,由于 Java 提供了 8 字节的有符号长度,因此涵盖了它。

标签: java binary-data


【解决方案1】:

DataInputStream 以 Big Endian 方向读取字节,但请检查一下:

3288596480 = 0xC4040000

反转字节,得到 0x04C4 = 1220

您只需阅读 Little Endian 中的值。关于标志的问题原来是一个红鲱鱼。

【讨论】:

  • 我在解析二进制文件时通常处理双精度的方法是使用现有方法读取一个长整数(是的,你会反转),然后调用 Double.longBitsToDouble 将长整数转换为双精度。
【解决方案2】:

在你的
Java 代码。您不会丢失任何信息。如果您以后需要输出它们,
进行转换,以免输出带符号的数字。

鉴于他们的名字:File Source IDHeader Size 我怀疑你
将对它们进行任何算术运算。如果你这样做,请小心。

或者,您可以在long(Java 中为 8 个字节)中读取它们,
并且不用担心算术运算,因为它们不会引起问题。

或者,您可以在 Java 中将值读取为字节数组,
然后将它们转换为 Java 代码中的正确类型。
这可能是最明确和最干净的解决方案。
但它需要更多的编码。

【讨论】:

  • 在 Java 中将带符号的 int 转换为正的 long:long l = i & 0xFFFFFFFFL;
  • @peter.petrov: 抱歉,阅读它不管用,它给我带来负面影响。我很困惑,很长需要 8 个字节,但标头大小是 4 个字节,这意味着我添加了 4 个额外的字节?
  • @Saddy_Grade 不确定您到底在尝试什么,但我建议您阅读“文件源 ID”和“标题大小”是字节数组。然后你从它们构造长值。见这里:stackoverflow.com/questions/1026761/…
  • @peter.petrov:我使用了readLong() & 0xFFFFFFFFL。它给了我积极但不正确的数字。
  • readLong() 读取 8 个字节。不只是 4。如果要读取 4 个字节,请使用 readInt() 并使用位掩码将结果转换为正长。
猜你喜欢
  • 1970-01-01
  • 2011-11-23
  • 1970-01-01
  • 2014-11-12
  • 1970-01-01
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多