Java 读取包含无符号数的二进制流
我想读取包含32位无符号整数和8位无符号整数的二进制文件。我已经知道了Java 读取包含无符号数的二进制流,java,kotlin,jvm,binaryfiles,java-io,Java,Kotlin,Jvm,Binaryfiles,Java Io,我想读取包含32位无符号整数和8位无符号整数的二进制文件。我已经知道了DataInputStream,但是它的方法readInt返回有符号整数,并且没有读取无符号整数的方法(有16位和8位整数的方法) 读取单独的字节并按位连接它们是“官方”的方法吗?通过数组将字节读入并使用位移位和按位或组合整数会显著降低性能吗?您可以使用 long value = Integer.toUnsignedLong(dataInputStream.readInt()); 这相当于Java 8之前的代码 long
DataInputStream
,但是它的方法readInt
返回有符号整数,并且没有读取无符号整数的方法(有16位和8位整数的方法)
读取单独的字节并按位连接它们是“官方”的方法吗?通过数组将字节读入并使用位移位和按位或组合整数会显著降低性能吗?您可以使用
long value = Integer.toUnsignedLong(dataInputStream.readInt());
这相当于Java 8之前的代码
long value = dataInputStream.readInt() & 0xFFFFFFFFL;
关键的一点是,有符号或无符号只是位模式的不同解释,但要读取四字节量,readInt()
总是足够的。上面的操作将转换为有符号的long
,这是一种能够覆盖无符号int的所有值的数据类型
但是由于int
已经保存了所有信息,因此无需立即将其转换为long
。用于表示有符号数字的符号甚至允许执行基本操作,即+
、-
和*
,而无需区分有符号数字和无符号数字。对于其他操作,Java 8引入了通过将int
值解释为unsigned来执行这些操作的方法:
我遇到的一个实际示例是解析类文件。这些文件的大小在某些地方编码为unsigned 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功能
(更简单的是,只要读者理解以下内容):
int size=input.readInt();
如果(大小<0)抛出新的IllegalArgumentException(
“截断类文件(属性大小”+(大小&0xFFFFFFFFFFFFL)+')”;
//只需使用int值
(另请参见)您想要哪种结果数据类型?您可以使用long value=Integer.toUnsignedLong(dataInputStream.readInt())例如,代码>。或者您只需使用int value=dataInputStream.readInt()
并在对算术产生影响时将该值解释为无符号。例如,对于+
、-
和*
来说,没有区别,对于/
和%
,使用和剩余无符号(…)
,同样地,比较(…)
和toUnsignedString(…)
。这可能解决了许多没有长算术运算的用例。要读取8位无符号整数,请使用@VGR OP已经确认存在8位和16位的方法…@JoopEggen方法readUnsignedByte()
实际上是作为返回0xFF&readByte()实现的代码>。同样地,toUnsignedLong
方法实现为returnx&0xFFFF\u ffffffl代码>(但请注意,它的八个F
s不是四个),尽管一些JVM可能会在合适的时候用一个内在操作替换它。大多数时候,当我需要这些东西时,我也会使用ByteBuffer
,而不是旧的DataInputStream
。除了支持其他端性外,它还允许切片、批量传输以及与字符集解码器的互操作性…
int size = input.readInt();
if(size < 0) throw new IllegalArgumentException(
"truncated class file (attribute size "+(size&0xFFFFFFFFL)+')');
// just use the int value