我问是因为我正在将字节流从 C 进程发送到 Java。在 C 端,32 位整数的 LSB 是第一个字节,MSB 是第 4 个字节。
所以我的问题是:在 Java 端,当我们读取从 C 进程发送的字节时,Java 端的字节序是什么?
一个后续问题:如果Java端的endian和发送的不一样,如何在它们之间进行转换?
我问是因为我正在将字节流从 C 进程发送到 Java。在 C 端,32 位整数的 LSB 是第一个字节,MSB 是第 4 个字节。
所以我的问题是:在 Java 端,当我们读取从 C 进程发送的字节时,Java 端的字节序是什么?
一个后续问题:如果Java端的endian和发送的不一样,如何在它们之间进行转换?
使用网络字节顺序(大端),这与 Java 使用的相同。请参阅 man htons 以了解 C 中的不同翻译器。
我通过 Google 偶然发现了这里,并得到了 Java 是big endian的答案。
阅读回复我想指出字节确实有一个字节顺序,虽然幸运的是,如果你只处理过“主流”微处理器,你不太可能遇到过它,因为英特尔、摩托罗拉和 Zilog 都是同意他们的 UART 芯片的移位方向,并且一个字节的 MSB将在他们的 CPU 中2**7
,LSB 将2**0
在他们的 CPU 中(我使用 FORTRAN 幂符号来强调这些东西有多古老 :))。
20 多年前,当我们用 Mac 计算机替换价值 1 万美元的接口硬件时,我遇到了一些航天飞机位串行下行链路数据的问题。很久以前有一篇关于它的 NASA 技术简报。table[0x01]=0x80
在每个字节从位流移入后,我只是使用了一个 256 个元素的查找表,位反转(等)。
Java 中没有无符号整数。所有整数都是有符号的并且是大端的。
在 C 端,每个字节的开头都有 tne LSB,左侧是 MSB,结尾是 MSB。
听起来您使用 LSB 作为最低有效位,是吗?LSB 通常代表最低有效字节。 字节序不是基于位,而是基于字节。
要将无符号字节转换为 Java 整数:
int i = (int) b & 0xFF;
要将 byte[] 中的无符号 32 位 little-endian 转换为 Java long(根据我的想法,未经测试):
long l = (long)b[0] & 0xFF;
l += ((long)b[1] & 0xFF) << 8;
l += ((long)b[2] & 0xFF) << 16;
l += ((long)b[3] & 0xFF) << 24;
这不可能影响 Java 中的任何内容,因为没有(直接的非 API)方法可以将某些字节直接映射到 Java 中的 int。
每个执行此操作或类似操作的 API 都非常精确地定义了行为,因此您应该查找该 API 的文档。
我会一个一个地读取字节,并将它们组合成一个长值。这样您就可以控制字节顺序,并且通信过程是透明的。
如果它适合您使用的协议,请考虑使用 DataInputStream,其行为定义非常明确。
如上所述,Java 是“大端”。这意味着如果您检查内存(至少在 Intel CPU 上),则 int 的 MSB 位于左侧。对于所有 Java 整数类型,符号位也在 MSB 中。
从“Little-endian”系统存储的二进制文件中读取 4 字节无符号整数需要在 Java 中进行一些调整。DataInputStream 的 readInt() 需要大端格式。
这是一个将四字节无符号值(HexEdit 显示为 01 00 00 00)读入值为 1 的整数的示例:
// Declare an array of 4 shorts to hold the four unsigned bytes
short[] tempShort = new short[4];
for (int b = 0; b < 4; b++) {
tempShort[b] = (short)dIStream.readUnsignedByte();
}
int curVal = convToInt(tempShort);
// Pass an array of four shorts which convert from LSB first
public int convToInt(short[] sb)
{
int answer = sb[0];
answer += sb[1] << 8;
answer += sb[2] << 16;
answer += sb[3] << 24;
return answer;
}
恕我直言,没有为 java 定义字节序。字节序是硬件之一,但java是高级别的并且隐藏了硬件,所以你不必担心这一点。
唯一与字节序相关的特性是 java lib 如何将 int 和 long 映射到 byte[] (反之亦然)。它使用 Big-Endian,这是最易读和最自然的:
int i=0xAABBCCDD
映射到
byte[] b={0xAA,0xBB,0xCC,0xDD}