2013-05-21 139 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

相關問題