DataInputStream 的 readLong():解析 Java 字节序如何将 8 字节变量拼装为 64 位整数
DataInputStream.readLong()从输入流读取8字节,严格按大端序(高位在前)组装为64位长整数。Java内置的readXxx均遵循网络字节序(大端)。若数据源为小端序,需手动反转字节顺序,常见做法是调用Long.reverseBytes()或通过ByteBuffer.order()设置为小端序后读取。注意字节序错误会导致数据解析错误。
DataInputStream.readLong():大端字节序的“铁律”
在Ja va里处理二进制数据时,DataInputStream.readLong() 是一个绕不开的方法。它的规则其实很简单:从输入流读取8个字节,严格按照大端序(Big-Endian)组装成一个 long 值。这意味着第一个读到的字节就是最高有效字节(bit 56–63),最后一个字节是最低有效字节(bit 0–7)。如果数据源是小端序,那就得自己动手反转字节顺序了。

DataInputStream.readLong() 从输入流中读取 8 个字节,并按大端序(Big-Endian)将其解释为一个 long 值——即最高有效字节(MSB)在前,最低有效字节(LSB)在后。
字节序决定字节如何“拼装”成数值
Ja va 所有内置的 readXxx() 方法(包括 readLong())都严格遵循网络字节序,也就是大端序。具体来说:
- 第 1 个读到的字节作为
long的高 8 位(bit 56–63) - 第 2 个字节作为 bit 48–55
- ……依此类推
- 第 8 个字节作为低 8 位(bit 0–7)
举个例子,如果流中连续 8 个字节是:0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,那么 readLong() 返回的值就是 0x0102030405060708L。
底层拼装逻辑(等效实现)
这个方法内部是怎么干的?其实并不神秘,大致可以理解为以下步骤(忽略异常和阻塞细节):
- 依次调用
readByte()八次,得到b0到b7 - 计算:
((b0 & 0xFFL) << 56) | ((b1 & 0xFFL) << 48) | ... | (b7 & 0xFFL) - 注意:每个
byte被提升为long后,需要与0xFFL按位与,避免符号扩展污染高位
说白了,就是移位加或运算,把8个字节拼成一个64位整数。
遇到小端数据怎么办?
DataInputStream 只认大端,不支持小端读取。如果源数据是小端(比如某些C程序或硬件协议输出),那就得手动干预:
- 先用
readFully(byte[8])读入一个字节数组 - 把数组倒序(
bytes[0]↔bytes[7],bytes[1]↔bytes[6],以此类推) - 然后用
ByteBuffer.wrap(reversed).getLong()或手动移位解析
与 ByteBuffer 的对比
相比之下,ByteBuffer 就灵活多了,支持切换字节序:buffer.order(ByteOrder.LITTLE_ENDIAN)。而 DataInputStream 固定大端,不可配置。这其实是由设计定位决定的——ByteBuffer 面向灵活二进制操作,DataInputStream 则是为配合 DataOutputStream 的标准 Ja va 数据序列化而生的,没那么通用,但也足够可靠。


































