一、字節順序
是指占用內存多於一個字節類型的數據在內存中的存放順序。
計算機電路先處理低位字節,效率比較高,因為計算都是從低位開始的。所以,計算機的內部處理都是小端字節序。
但是,網絡傳輸、文件儲存、人類讀寫習慣使用大端字節序。
java中一個int型數據占用4個字節,假如有一個16進制的int數,int value =(高字節) 0x01020304 (低字節)
小端字節序(little endian):低字節數據存放在內存低地址
大端字節序(bigendian): 低字節數據存放在高地址處
主機字節序跟CPU有關的,IA架構(Intel、AMD)的CPU中是Little-Endian
所謂的JAVA字節序指的是在JAVA虛擬機中多字節類型數據的存放順序,JAVA字節序也是BIG-ENDIAN。
由於JVM會根據底層的操作系統和CPU自動進行字節序的轉換,
所以我們使用java進行網絡編程,幾乎感覺不到字節序的存在。
二、ByteBuffer 示例
public static void byteOrder() { int x = 0x01020304; ByteBuffer bb = ByteBuffer.wrap(new byte[4]); bb.asIntBuffer().put(x); System.out.println( bb.order() + " 內存數據 " + Arrays.toString(bb.array())); bb.order(ByteOrder.LITTLE_ENDIAN); bb.asIntBuffer().put(x); System.out.println( bb.order() + " 內存數據 " + Arrays.toString(bb.array())); }
BIG_ENDIAN 內存數據 [1, 2, 3, 4]
LITTLE_ENDIAN 內存數據 [4, 3, 2, 1]
三、Java 與 JavaScript 字節轉換
如果通信的雙方都是Java,則根本不用考慮字節序的問題了。
Java 的 byte 范圍是[-128, 127],
JavaScript 的 byte 范圍是[0, 256]
四、int 與 byte Array 轉換示例
轉換時使用相同的字節序
// 生成4個字節的網絡字節序,網絡傳輸使用大端字節序,相當於int2ByteArray byte[] getNetworkBytesOrder(int sourceNumber) { byte[] orderBytes = new byte[4]; orderBytes[3] = (byte) (sourceNumber & 0xFF); orderBytes[2] = (byte) (sourceNumber >> 8 & 0xFF); orderBytes[1] = (byte) (sourceNumber >> 16 & 0xFF); orderBytes[0] = (byte) (sourceNumber >> 24 & 0xFF); return orderBytes; } // 還原4個字節的網絡字節序, 相當於byteArray2Int int recoverNetworkBytesOrder(byte[] orderBytes) { int sourceNumber = 0; for (int i = 0; i < 4; i++) { sourceNumber <<= 8; sourceNumber |= orderBytes[i] & 0xff; } return sourceNumber; }
五
System.out.println(Arrays.toString(intToByteArray(32))); System.out.println(Arrays.toString(intToByteArray(145))); System.out.println(Arrays.toString(intToByteArray(256))); System.out.println(Arrays.toString(intToByteArray2(32))); System.out.println(Arrays.toString(intToByteArray2(145))); System.out.println(Arrays.toString(intToByteArray2(256))); //還原 System.out.println(byteArrayToInt2(intToByteArray2(145))); System.out.println(byteArrayToInt(intToByteArray2(145)));
輸出
[0, 0, 0, 32]
[0, 0, 0, -111]
[0, 0, 1, 0]
[0, 0, 0, 32]
[0, 0, 0, -111]
[0, 0, 1, 0]
145
145
public static byte[] intToByteArray(int i) { byte[] result = new byte[4]; result[0] = (byte)((i >> 24) & 0xFF); result[1] = (byte)((i >> 16) & 0xFF); result[2] = (byte)((i >> 8) & 0xFF); result[3] = (byte)(i & 0xFF); return result; } public static byte[] intToByteArray2(int i) { return ByteBuffer .allocate(4) // 默認大端字節序 // .order(ByteOrder.LITTLE_ENDIAN) .putInt(i) .array(); } public static int byteArrayToInt2(byte[] byteArray) { int value = 0; for (int i = 0; i < 4; i++) { int shift = (4 - 1 - i) * 8; value += (byteArray[i] & 0x000000FF) << shift; } return value; } public static int byteArrayToInt(byte [] byteArray){ return ByteBuffer.wrap(byteArray) // 默認大端字節序 // .order(ByteOrder.LITTLE_ENDIAN) .getInt(); }