2016-03-02 95 views
1

我有一個long。我知道這個long不是很大。實際上,它可以編碼爲7字節的無符號整數。ByteBuffer putLong()長度爲7個字節的值

我想編寫使用ByteBuffer和小尾數我longbyte[7]

long myLong = ... //some value 
byte[] myLongBytes = ByteBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN).putLong(myLong).array(); 

拋出IndexOutOfBoundsException,當然。我可以用ByteBuffer做這個嗎?我應該以不同的方式去做嗎?

+0

實際上是8字節 – Pooya

+0

@Pooya但我需要將它編碼爲7個字節,因爲我知道值不是那麼大......我根本不需要8個字節。 – vojta

+0

@vojta JVM不知道這一點,並嘗試將8字節放入7字節分配的緩衝區中。你可以簡單地使用8個字節,然後丟棄最重要的字節(如果它是正面的課程) – Pooya

回答

4

(假設如OP表示小端排序的字節順序)

(假設要從存儲長56至少顯著位)

long myLong = someLongValue & 0x00FFFFFFFFFFFFFFL; 
ByteBuffer bb = ByteBuffer.allocate(xxx).order(ByteOrder.LITTLE_ENDIAN); 

選項A:寫64位長和比移除一個字節

bb.putLong(myLong); 
bb.position(bb.position()-1); 

爲尾寫(即,該長是將ByteBuffer最後寫入):

bb.putLong(myLong); 
bb.limit(bb.position()-1); 

請注意,只有您可以確保ByteBuffer容量足夠大以適應此臨時額外字節,此方法纔有效。

一些示例情況下,這種做法應該是OK:

  • 如果這56位值總是跟着另一場(那麼你肯定有一些能力儲備)

  • 當你嚴格使用使用ByteBuffer舒適的字節數組寫入(這是由您的文章暗​​示)的ByteBuffer.limit()功能,而不是(AB)

選項B:寫長「每份」

bb.putInt((int)myLong); 
bb.putShort((short)(myLong>>>32)); 
bb.put((byte)(myLong>>>48)); 

這個每次都有效。

選項C:使用字節[],而不是長期

您可以考慮使用的字節數組,而不是長(取決於你的使用情況)。

祝你好運!

+0

選項A是好的,只要你不介意寫一個額外的字節,如果這是一個問題,選項B更好。選項C意味着使用我給出的答案。選項B +1 –

-2

待辦事項如下

字節[] myLongBytes = ByteBuffer.allocate(Long.SIZE/Byte.SIZE).putLong(myLong).array();

+0

但我需要將它編碼成只有7個字節,因爲我知道值不是那麼大......我根本不需要8個字節。 – vojta

-2

Java long是64位所以64/8 = 8字節的值,所以你沒有分配足夠的空間。分配8個字節,而不是7個。

+0

但我只需要將它編碼爲7個字節,因爲我知道這個值不是那麼大......我根本不需要8個字節。 – vojta

+0

然後將長整型轉換爲字節數組,並只將該數組的最後7個字節寫入緩衝區(最高字節先在Java中)。有關如何轉換,請參閱http://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java。 – h22

5

你需要寫一次一個字節,例如(基於java.nio.Bits)

static private long makeLong(byte b6, byte b5, byte b4, 
          byte b3, byte b2, byte b1, byte b0) 
{ 
    return ((((long)b6 & 0xff) << 48) | 
      (((long)b5 & 0xff) << 40) | 
      (((long)b4 & 0xff) << 32) | 
      (((long)b3 & 0xff) << 24) | 
      (((long)b2 & 0xff) << 16) | 
      (((long)b1 & 0xff) << 8) | 
      (((long)b0 & 0xff)  )); 
} 

static long getLongL(ByteBuffer bb, int bi) { 
    return makeLong(bb.get(bi + 6), 
        bb.get(bi + 5), 
        bb.get(bi + 4), 
        bb.get(bi + 3), 
        bb.get(bi + 2), 
        bb.get(bi + 1), 
        bb.get(bi )); 
} 

private static byte long6(long x) { return (byte)(x >> 48); } 
private static byte long5(long x) { return (byte)(x >> 40); } 
private static byte long4(long x) { return (byte)(x >> 32); } 
private static byte long3(long x) { return (byte)(x >> 24); } 
private static byte long2(long x) { return (byte)(x >> 16); } 
private static byte long1(long x) { return (byte)(x >> 8); } 
private static byte long0(long x) { return (byte)(x  ); } 

static void putLongL(ByteBuffer bb, int bi, long x) { 
    bb.put(bi + 6, long6(x)); 
    bb.put(bi + 5, long5(x)); 
    bb.put(bi + 4, long4(x)); 
    bb.put(bi + 3, long3(x)); 
    bb.put(bi + 2, long2(x)); 
    bb.put(bi + 1, long1(x)); 
    bb.put(bi , long0(x)); 
} 

一般情況下,我避免犯微觀優化像這樣因爲它而收效甚微恕我直言,增加了複雜性。如果你想節省空間,我建議使用類似停止位編碼的技術,每隔7位使用一個字節。即一個很長的可能只使用1個字節的小值,但可能會更大。

+2

沒有太多的代碼這麼瑣碎的任務? – h22

+0

@ h22歡迎您縮短它。 ;)由於沒有硬件支持,讀取/寫入7個字節的值並不那麼簡單。 –

+0

@PeterLawrey我的答案呢? – vlp