我们正在使用Java ByteBuffer与C ++服务器进行套接字通信。我们知道Java是Big-endian,而Socket通信也是Big-endian。因此,只要字节流被Java接收并放入ByteBuffer,我们就会调用getInt()来获取值。没问题,没有转换。
但是如果我们以某种方式将ByteBuffer字节顺序专门设置为Little-endian(我的同事实际上已经这样做了),
当数据放入ByteBuffer时,Java会自动将Big-endian转换为Little-endian吗?
那么Little-endian版本的getInt()会给你一个正确的值吗?
我想上面两个问题的答案是肯定的。但是当我尝试验证我的猜测并试图找到getInt()在ByteBuffer中的工作原理时,我发现它是一个抽象方法。 ByteBuffer的唯一子类是MappedByteBuffer类,它没有实现抽象的getInt()。那么getInt()方法的实现在哪里?
对于发送,因为我们使用的是Little-endian ByteBuffer,我们需要在放入套接字之前将它们转换为Big-endian字节。
答案 0 :(得分:9)
ByteBuffer将自动使用您指定的字节顺序。 (默认情况下为Big endian)
ByteBuffer bb =
// to use big endian
bb.order(ByteOrder.BIG_ENDIAN);
// to use little endian
bb.order(ByteOrder.LITTLE_ENDIAN);
// use the natural order of the system.
bb.order(ByteOrder.nativeOrder());
直接和堆ByteBuffers将按照您的指定重新排序字节。
答案 1 :(得分:3)
那么getInt()方法的实现在哪里?
ByteBuffer确实是一个抽象类。有几种方法可以创建字节缓冲区:
在我的JDK中,这些创建了内部类HeapByteBuffer
和DirectByteBuffer
的实例。他们各自的getInt
函数如下:
// HeapByteBuffer
public int getInt() {
return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
}
public int getInt(int i) {
return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
}
和
// DirectByteBuffer
private int getInt(long a) {
if (unaligned) {
int x = unsafe.getInt(a);
return (nativeByteOrder ? x : Bits.swap(x));
}
return Bits.getInt(a, bigEndian);
}
public int getInt() {
return getInt(ix(nextGetIndex((1 << 2))));
}
public int getInt(int i) {
return getInt(ix(checkIndex(i, (1 << 2))));
}
在上面,nativeByteOrder
和bigEndian
是两个布尔成员,分别表示 - 并且有点冗余 - 是否配置的字节顺序:(a)匹配本机字节顺序; (b)是大端。