使用ByteBuffer将long转换为"无符号,网络字节顺序为4字节整数"

The*_*eLQ 1 java nio bytebuffer bit-shift

我正在使用的协议要求将文件中的当前位置作为"无符号,网络字节顺序的4字节整数"发回.关于这个问题有几个问题,但他们假设我使用的是Integers,而不是Longs

我试图将其移植到NIO的ByteBuffer,以便它可以在套接字通道中发送:

long bytesTransfered = ... some number of bytes transfered...
//TODO: What does this actually do?
outBuffer[0] = (byte) ((bytesTransfered >> 24) & 0xff);
outBuffer[1] = (byte) ((bytesTransfered >> 16) & 0xff);
outBuffer[2] = (byte) ((bytesTransfered >> 8) & 0xff);
//TODO: Why does netbeans say this does nothing?
outBuffer[3] = (byte) ((bytesTransfered >> 0) & 0xff);
Run Code Online (Sandbox Code Playgroud)

他们在ByteBuffer中的任何方法都能实现这一目标吗?希望以一种更加明显,自我描述的方式,然后上面的位移魔法?

par*_*fal 6

无论是有符号还是无符号,这些位都是相同的.

如果将a转换long为a int,则JVM会丢弃高位.当int将a 提升为a 时,问题就出现了long:Java将对值进行符号扩展,long用最重要的位填充高位int.

要解决此问题,只需将一个掩码应用于long.以下内容应该清楚说明:

long value = Integer.MAX_VALUE + 1234L;
System.out.println("original value    = " + value);

int iValue = (int)value;
System.out.println("value as int      = " + iValue);
byte[] array = new byte[4];

ByteBuffer buf = ByteBuffer.wrap(array);
buf.putInt(0, iValue);

int iRetrieved = buf.getInt(0);
System.out.println("int from buf      = " + iRetrieved);

long retrieved = iRetrieved;
System.out.println("converted to long = " + retrieved);

retrieved = retrieved & 0xFFFFFFFFL;
System.out.println("high bytes masked = " + retrieved);
Run Code Online (Sandbox Code Playgroud)

但是,请注意,您仍然只有32位.如果文件大小超过4Gb,您将无法将其装入4个字节(如果您不得不担心文件> 2G,那么您应该担心文件> 4G).