在一個物聯往項目中,需要java雲平台與一個客戶端做socket定制協議的通信;然而在第一次測試時,並沒有按照預想的那樣完成解析。查找資料以后是因為客戶端的數據讀取方式為小端模式,而java默認采用大端模式。
在計算機系統中,我們是以字節為單位的,每個地址單元都對應着一個字節,一個字節為 8bit。但是在C語言中除了8bit的char之外,還有16bit的short型,32bit的long型(要看具體的編譯器),另外,對於位數大於 8位的處理器,例如16位或者32位的處理器,由於寄存器寬度大於一個字節,那么必然存在着一個如何將多個字節安排的問題。因此就導致了大端存儲模式和小端存儲模式。
目前Intel的80x86系列芯片是唯一還在堅持使用小端的芯片,而MIPS和ARM等芯片要么采用全部大端的方式儲存,要么提供選項支持大端——可以在大小端之間切換。另外,對於大小端的處理也和編譯器的實現有關,在C語言中,默認是小端(但在一些對於單片機的實現中卻是基於大端,比如Keil 51C),Java是平台無關的,默認是大端。在網絡上傳輸數據普遍采用的都是大端。
如果遇到了大端與小端之間的通信。應該遵照大小端的數據讀取原理,做相應的轉換。(以java的大端模式為例)
現在以java的32位的int型數據為例子,做轉換示例;
如下:是大端int轉化為小端的byte數組:將int型的4個高位16進制數逆序放入字節數組中;
public static byte[] intToMinByteArray(int i) { byte[] result = new byte[4]; //由高位到低位 result[3] = (byte) ((i >> 24) & 0xFF); result[2] = (byte) ((i >> 16) & 0xFF); result[1] = (byte) ((i >> 8) & 0xFF); result[0] = (byte) (i & 0xFF); return result; }
如下是小端數組轉化為大端int數的示例:采用字符串表示的16進制數來轉換為Integer的api。
public static int byteLittleEndianToInt(byte[] bytes) { String nubHexStr = ""; byte[] temp = new byte[bytes.length]; for (int i = 0; i < bytes.length; i++) { System.out.println("值:" + bytes[bytes.length - i - 1]); System.out.println("對應的16進制值:"+Integer.toHexString(bytes[bytes.length - i - 1])); nubHexStr += Integer.toHexString(bytes[bytes.length - i - 1]); } System.out.println("16進制:" + nubHexStr); return Integer.parseInt(nubHexStr, 16); }
以上代碼來自Felix。