【问题标题】:Read binary stream containing unsigned numbers读取包含无符号数的二进制流
【发布时间】:2020-11-18 03:45:40
【问题描述】:

我想读取包含 32 位无符号整数和 8 位无符号整数的二进制文件。我已经知道DataInputStream,但是它的方法readInt 返回有符号整数并且没有读取无符号整数的方法(16 位和8 位整数有这样的方法)。

读取单独的字节并按位连接它们是“官方”的方式吗?将字节读入ByteArray 并使用位移位和按位ors 从其中组合整数会显着降低性能吗?

【问题讨论】:

  • 你想要哪种结果数据类型?
  • 例如,您可以使用long value = Integer.toUnsignedLong​(dataInputStream.readInt());。或者您只需使用int value = dataInputStream.readInt(); 并将值解释 为无符号,只要它对算术产生影响。例如。对于+-*,没有区别,对于/%,使用Integer.divideUnsigned​(…)remainderUnsigned​(…),同样,compareUnsigned​(…)toUnsignedString​(…)。这可以解决很多没有long 算术的用例。
  • 要读取 8 位无符号整数,请使用 readUnsignedByte
  • @VGR OP 确实已经承认了 8 位和 16 位方法的存在……
  • @JoopEggen 方法readUnsignedByte() 实际上实现为return 0xFF & readByte();。同样,toUnsignedLong 方法实现为 return x & 0xFFFF_FFFFL;(但请注意,它的八个 Fs 不是四个),尽管某些 JVM 可能会在合适时将其替换为内部操作。大多数时候,当我需要这些东西时,我也会使用ByteBuffer,而不是旧的DataInputStream。除了支持其他字节序之外,它还允许切片、批量传输以及与字符集解码器的互操作性……

标签: java kotlin jvm binaryfiles java-io


【解决方案1】:

你可以使用

long value = Integer.toUnsignedLong​(dataInputStream.readInt());

这相当于 Java 8 之前的代码

long value = dataInputStream.readInt() & 0xFFFFFFFFL;

关键是有符号或无符号只是位模式的不同解释,但要读取四个字节的数量,readInt() 总是足够的。上面的操作转换为有符号的long,一种能够覆盖所有无符号整数值的数据类型。

但由于int 已经保存了所有信息,因此无需立即将其转换为long。用于表示有符号数的Two’s Complement 甚至允许执行基本操作,即+-*,而不区分有符号数和无符号数。对于其他操作,Java 8 引入了通过将 int 值解释为无符号来执行它们的方法:

我遇到的一个实际例子是解析类文件。这些文件的大小在某些地方已编码为 un​​signed int,但对于大多数标准 Java API,类文件以字节数组或 ByteBuffer 实例的形式提供,其中不能包含超过 2³¹ 字节。因此,处理更大的数字对于无论如何都不正确的事情是不必要的复杂化,因为包含如此大尺寸规范的类文件必须被截断。

所以处理这个的代码看起来基本上是这样的:

int size = input.readInt();
if(Integer.compareUnsigned(size, Integer.MAX_VALUE)>0) throw new IllegalArgumentException(
    "truncated class file (attribute size "+Integer.toUnsignedString(size)+')');
// just use the int value

或没有 Java 8 功能
(更简单,只要读者看懂Two’s Complement):

int size = input.readInt();
if(size < 0) throw new IllegalArgumentException(
    "truncated class file (attribute size "+(size&0xFFFFFFFFL)+')');
// just use the int value

(另见this answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多