2013-05-21 69 views
0

我正在使用的协议要求将文件中的当前位置作为“无符号,网络字节顺序的4字节整数”发回。有这个几个问题,但他们假设我使用整数,而不是多头使用ByteBuffer将long转换为“无符号,网络字节顺序的4字节整数”

我试图端口这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); 

是他们的任何方法在ByteBuffer中完成了这个?希望以更明显,自我描述的方式,然后上面的变化魔术?

+1

如果你使用'long'为什么你只需要4个字节?相反,如果你只需要4个字节,坚持'long'是毫无意义的。 – EJP

回答

4

无论是有符号还是无符号,位都是相同的。

如果您将long转换为int,则JVM丢弃高位。将int提升为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); 

然而,要知道,你仍然只有32位。如果文件大小大于4Gb,则无法将其适用于4个字节(如果您不必担心文件大于2G,那么您应该担心文件大于4G)。

+0

+1感谢您的详细解释。 – TheLQ

3

这正是ByteBuffer.putInt()的用途。你说你正在使用long,但你也只想写四个字节,所以你必须把你的long转换成int。或者使用putLong()并获得8个字节。

+0

看看另一个删除的答案。从字面上看,第二句话说:“这里有几个问题,但是他们假设我使用整数,而不是长整数” – TheLQ

+1

所以将它转换为int。请参阅编辑。 – EJP

+0

我想问题是在Java int中签名。该协议假定我使用的是未签名的整数,因此可以支持大于2GB的文件大小。长期的要求不存在,因为它闪亮,它存在的原因 – TheLQ

相关问题