簡體   English   中英

Java中的字節數組和Int轉換

[英]Byte Array and Int conversion in Java

我對這兩個函數有一些困難: byteArrayToIntintToByteArray

問題是,如果我使用一個來到另一個並且結果到達前者,結果會有所不同,您可以從下面的示例中看到。

我找不到代碼中的錯誤。 任何想法都非常受歡迎。 謝謝。

public static void main(String[] args)
{
    int a = 123;
    byte[] aBytes = intToByteArray(a);
    int a2 = byteArrayToInt(aBytes);

    System.out.println(a);         // prints '123'
    System.out.println(aBytes);    // prints '[B@459189e1'
    System.out.println(a2);        // prints '2063597568
            System.out.println(intToByteArray(a2));  // prints '[B@459189e1'
}

public static int byteArrayToInt(byte[] b) 
{
    int value = 0;
    for (int i = 0; i < 4; i++) {
        int shift = (4 - 1 - i) * 8;
        value += (b[i] & 0x000000FF) << shift;
    }
    return value;
}

public static byte[] intToByteArray(int a)
{
    byte[] ret = new byte[4];
    ret[0] = (byte) (a & 0xFF);   
    ret[1] = (byte) ((a >> 8) & 0xFF);   
    ret[2] = (byte) ((a >> 16) & 0xFF);   
    ret[3] = (byte) ((a >> 24) & 0xFF);
    return ret;
}

你的方法應該是(類似的)

public static int byteArrayToInt(byte[] b) 
{
    return   b[3] & 0xFF |
            (b[2] & 0xFF) << 8 |
            (b[1] & 0xFF) << 16 |
            (b[0] & 0xFF) << 24;
}

public static byte[] intToByteArray(int a)
{
    return new byte[] {
        (byte) ((a >> 24) & 0xFF),
        (byte) ((a >> 16) & 0xFF),   
        (byte) ((a >> 8) & 0xFF),   
        (byte) (a & 0xFF)
    };
}

使用以下代碼測試了這些方法:

Random rand = new Random(System.currentTimeMillis());
byte[] b;
int a, v;
for (int i=0; i<10000000; i++) {
    a = rand.nextInt();
    b = intToByteArray(a);
    v = byteArrayToInt(b);
    if (a != v) {
        System.out.println("ERR! " + a + " != " + Arrays.toString(b) + " != " + v);
    }
}
System.out.println("Done!");

這是很多工作:

public static int byteArrayToLeInt(byte[] b) {
    final ByteBuffer bb = ByteBuffer.wrap(b);
    bb.order(ByteOrder.LITTLE_ENDIAN);
    return bb.getInt();
}

public static byte[] leIntToByteArray(int i) {
    final ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE);
    bb.order(ByteOrder.LITTLE_ENDIAN);
    bb.putInt(i);
    return bb.array();
}

此方法使用java.nio包中的Java ByteBufferByteOrder功能。 在需要可讀性的情況下,此代碼應該是首選。 它也應該很容易記住。

我在這里顯示了Little Endian字節順序。 要創建Big Endian版本,您可以簡單地省略對order(ByteOrder)的調用order(ByteOrder)


在性能優先於可讀性的代碼中(大約快10倍):

public static int byteArrayToLeInt(byte[] encodedValue) {
    int value = (encodedValue[3] << (Byte.SIZE * 3));
    value |= (encodedValue[2] & 0xFF) << (Byte.SIZE * 2);
    value |= (encodedValue[1] & 0xFF) << (Byte.SIZE * 1);
    value |= (encodedValue[0] & 0xFF);
    return value;
}

public static byte[] leIntToByteArray(int value) {
    byte[] encodedValue = new byte[Integer.SIZE / Byte.SIZE];
    encodedValue[3] = (byte) (value >> Byte.SIZE * 3);
    encodedValue[2] = (byte) (value >> Byte.SIZE * 2);   
    encodedValue[1] = (byte) (value >> Byte.SIZE);   
    encodedValue[0] = (byte) value;
    return encodedValue;
}

只需將字節數組索引反轉為從0到3的計數,即可創建此代碼的Big Endian版本。


筆記:

  • 在Java 8中,您還可以使用Integer.BYTES常量,該常量比Integer.SIZE / Byte.SIZE更簡潔。

您正在交換兩種方法之間的字節順序 你有intToByteArray(int a)將低位分配給ret[0] ,但是byteArrayToInt(byte[] b)b[0]賦給結果的高位。 您需要反轉其中一個,例如:

public static byte[] intToByteArray(int a)
{
    byte[] ret = new byte[4];
    ret[3] = (byte) (a & 0xFF);   
    ret[2] = (byte) ((a >> 8) & 0xFF);   
    ret[1] = (byte) ((a >> 16) & 0xFF);   
    ret[0] = (byte) ((a >> 24) & 0xFF);
    return ret;
}

您還可以將BigInteger用於可變長度字節。 您可以將其轉換為Long,Integer或Short,以滿足您的需求。

new BigInteger(bytes).intValue();

或表示極性:

new BigInteger(1, bytes).intValue();

要獲取字節只是:

new BigInteger(bytes).toByteArray()

我喜歡owlstead的原始答案,如果你不喜歡在每個方法調用上創建一個ByteBuffer的想法,那么你可以通過調用它的.clear().flip()方法來重用ByteBuffer

ByteBuffer _intShifter = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE)
                                   .order(ByteOrder.LITTLE_ENDIAN);

public byte[] intToByte(int value) {
    _intShifter.clear();
    _intShifter.putInt(value);      
    return _intShifter.array();
}

public int byteToInt(byte[] data)
{
    _intShifter.clear();
    _intShifter.put(data, 0, Integer.SIZE / Byte.SIZE);
    _intShifter.flip();
    return _intShifter.getInt();
}

我在com.google.common.primitives中找到了一個簡單的方法,它位於[Maven:com.google.guava:guava:12.0.1]中

long newLong = Longs.fromByteArray(oldLongByteArray);
int newInt = Ints.fromByteArray(oldIntByteArray);

試試看:)

我仔細看了很多像這樣的問題,發現這個帖子 ......我不喜歡每種類型的轉換代碼都是重復的,所以我做了一個通用的方法來執行任務:

public static byte[] toByteArray(long value, int n)
{
    byte[] ret = new byte[n];
    ret[n-1] = (byte) ((value >> (0*8) & 0xFF);   
    ret[n-2] = (byte) ((value >> (1*8) & 0xFF);   
    ...
    ret[1] = (byte) ((value >> ((n-2)*8) & 0xFF);   
    ret[0] = (byte) ((value >> ((n-1)*8) & 0xFF);   
    return ret;
}

查看完整帖子

/ *抱歉這是正確的* /

     public byte[] IntArrayToByteArray(int[] iarray , int sizeofintarray)
     {
       final ByteBuffer bb ;
       bb = ByteBuffer.allocate( sizeofintarray * 4);
       for(int k = 0; k < sizeofintarray ; k++)
       bb.putInt(k * 4, iar[k]);
       return bb.array();
     }

而不是分配空間,等等,使用來自java.nio ByteBuffer的方法....

byte[] arr = { 0x01, 0x00, 0x00, 0x00, 0x48, 0x01};

// say we want to consider indices 1, 2, 3, 4 {0x00, 0x00, 0x00, 0x48};
ByteBuffer bf = ByteBuffer.wrap(arr, 1, 4); // big endian by default
int num = bf.getInt();    // 72

現在,走另一條路。

ByteBuffer newBuf = ByteBuffer.allocate(4);
newBuf.putInt(num);
byte[] bytes = newBuf.array();  // [0, 0, 0, 72] {0x48 = 72}

這是我的實施

public static byte[] intToByteArray(int a) {
    return BigInteger.valueOf(a).toByteArray();
}

public static int byteArrayToInt(byte[] b) {
    return new BigInteger(b).intValue();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM