大端小端模式
一、什麼是大小端模式
大端模式,是指資料的高位元組儲存在記憶體的低位址中,而資料的低位元組儲存在記憶體的高位址中,這樣的存儲模式有點兒類似于把資料當作字元串順序處理:位址由小向大增加,而資料從高位往低位放;這和我們的閱讀習慣一緻。
小端模式,是指資料的高位元組儲存在記憶體的高位址中,而資料的低位元組儲存在記憶體的低位址中。
舉個例子:
以 unsigned int value = 0x12345678來表示,unsigned char buf[4]存放。
Big-Endian: 低位址存放高位,如下:
高位址
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
低位址
Little-Endian: 低位址存放低位,如下:
高位址
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
--------------
低位址
舉個例子:
java中的大小端轉換
import java.util.Arrays;
class Test {
public static void main(String[] args) {
int a = 10;
byte[] little = intToByteLittle(a);
byte[] big = intToByteBig(a);
System.out.println("little:"+ Arrays.toString(little)); // [10, 0, 0, 0]
System.out.println("big:"+ Arrays.toString(big)); // [0, 0, 0, 10]
}
/**
* 将int轉為低位元組在前,高位元組在後的byte數組(小端)
*
* @param n int
* @return byte[]
*/
public static byte[] intToByteLittle(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 将int轉為高位元組在前,低位元組在後的byte數組(大端)
*
* @param n int
* @return byte[]
*/
public static byte[] intToByteBig(int n) {
byte[] b = new byte[4];
b[3] = (byte) (n & 0xff);
b[2] = (byte) (n >> 8 & 0xff);
b[1] = (byte) (n >> 16 & 0xff);
b[0] = (byte) (n >> 24 & 0xff);
return b;
}
}
二、為什麼要有大小端
這個問題沒有定論,就像汽車的方向盤有在左邊的,也有在右邊的。
三、大小端與什麼有關?
程式設計語言和大小端沒有關系,影響大小端的是
編譯器
/
CPU
Android 是大端還是小端?
上面講過,CPU和編譯器才是影響大端小端的關鍵,Android系統的碎片化,也說不好Android是大端還是小端。
有必要知道它是大端還是小端嗎? 沒有必要。
傳一個位元組會變嗎? 不會。
因為在資料轉換的過程中就已經指定了是以大端還是小端的規則,相應的,如果傳輸給其它硬體或者背景,隻需要按此規則解析即可。
三、Java 轉換大小端的工具類
package com.demo.my.ble_client.utils;
import java.util.Arrays;
public class ByteUtils {
/**
* 兩個byte[]是否相同
* @param data1
* @param data2
* @return
*/
public static boolean arrayEquals(byte[] data1, byte[] data2) {
return Arrays.equals(data1, data2);
}
/**
* 截取byte[]
* @param data
* @param position
* @param length
* @return
*/
public static byte[] subArray(byte[] data, int position, int length) {
byte[] temp = new byte[length];
System.arraycopy(data, position, temp, 0, length);
return temp;
}
/**
* 解決java中byte輸出可能為負數的問題。
* @param b
* @return
*/
public static Integer byteToInteger(Byte b) {
return 0xff & b;
}
/**
* 拼接byte[] 和 byte[]
*
* @param bytes1
* @param bytes2
* @return
*/
public static byte[] byteMerger(byte[] bytes1, byte[] bytes2) {
byte[] bytes3 = new byte[bytes1.length + bytes2.length];
System.arraycopy(bytes1, 0, bytes3, 0, bytes1.length);
System.arraycopy(bytes2, 0, bytes3, bytes1.length, bytes2.length);
return bytes3;
}
/**
* 拼接byte 和 byte[]
*
* @param byte1
* @param bytes2
* @return
*/
public static byte[] byteMerger(byte byte1, byte[] bytes2) {
byte[] bytes3 = new byte[1 + bytes2.length];
bytes3[0] = byte1;
System.arraycopy(bytes2, 0, bytes3, 1, bytes2.length);
return bytes3;
}
/**
* 拼接byte[] 和 byte
*
* @param bytes1
* @param byte2
* @return
*/
public static byte[] byteMerger(byte[] bytes1, byte byte2) {
byte[] bytes3 = new byte[1 + bytes1.length];
System.arraycopy(bytes1, 0, bytes3, 0, bytes1.length);
bytes3[bytes3.length - 1] = byte2;
return bytes3;
}
/**
* 拼接三個數組
*
* @param bt1
* @param bt2
* @param bt3
* @return
*/
public static byte[] byteMerger3(byte[] bt1, byte[] bt2, byte[] bt3) {
byte[] data = new byte[bt1.length + bt2.length + bt3.length];
System.arraycopy(bt1, 0, data, 0, bt1.length);
System.arraycopy(bt2, 0, data, bt1.length, bt2.length);
System.arraycopy(bt3, 0, data, bt1.length + bt2.length, bt3.length);
return data;
}
/**
* Byte[] 與 int 互轉
* =============================================================================================
*/
/**
* 将int轉為高位元組在前,低位元組在後的byte數組(大端)
*
* @param n int
* @return byte[]
*/
public static byte[] intToByteBig(int n) {
byte[] b = new byte[4];
b[3] = (byte) (n & 0xff);
b[2] = (byte) (n >> 8 & 0xff);
b[1] = (byte) (n >> 16 & 0xff);
b[0] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 将int轉為低位元組在前,高位元組在後的byte數組(小端)
*
* @param n int
* @return byte[]
*/
public static byte[] intToByteLittle(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* byte數組到int的轉換(小端)
*
* @param bytes
* @return
*/
public static int bytes2IntLittle(byte[] bytes) {
int int1 = bytes[0] & 0xff;
int int2 = (bytes[1] & 0xff) << 8;
int int3 = (bytes[2] & 0xff) << 16;
int int4 = (bytes[3] & 0xff) << 24;
return int1 | int2 | int3 | int4;
}
/**
* byte數組到int的轉換(大端)
*
* @param bytes
* @return
*/
public static int bytes2IntBig(byte[] bytes) {
int int1 = bytes[3] & 0xff;
int int2 = (bytes[2] & 0xff) << 8;
int int3 = (bytes[1] & 0xff) << 16;
int int4 = (bytes[0] & 0xff) << 24;
return int1 | int2 | int3 | int4;
}
/**
* Byte[] 與 short 互轉
* =============================================================================================
*/
/**
* 将short轉為高位元組在前,低位元組在後的byte數組(大端)
*
* @param n short
* @return byte[]
*/
public static byte[] shortToByteBig(short n) {
byte[] b = new byte[2];
b[1] = (byte) (n & 0xff);
b[0] = (byte) (n >> 8 & 0xff);
return b;
}
/**
* 将short轉為低位元組在前,高位元組在後的byte數組(小端)
*
* @param n short
* @return byte[]
*/
public static byte[] shortToByteLittle(short n) {
byte[] b = new byte[2];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
return b;
}
/**
* 讀取小端byte數組為short
*
* @param b
* @return
*/
public static short byteToShortLittle(byte[] b) {
return (short) (((b[1] << 8) | b[0] & 0xff));
}
/**
* 讀取大端byte數組為short
*
* @param b
* @return
*/
public static short byteToShortBig(byte[] b) {
return (short) (((b[0] << 8) | b[1] & 0xff));
}
/**
* Byte[] 與 long 互轉
* =============================================================================================
*/
/**
* long類型轉byte[] (大端)
*
* @param n
* @return
*/
public static byte[] longToBytesBig(long n) {
byte[] b = new byte[8];
b[7] = (byte) (n & 0xff);
b[6] = (byte) (n >> 8 & 0xff);
b[5] = (byte) (n >> 16 & 0xff);
b[4] = (byte) (n >> 24 & 0xff);
b[3] = (byte) (n >> 32 & 0xff);
b[2] = (byte) (n >> 40 & 0xff);
b[1] = (byte) (n >> 48 & 0xff);
b[0] = (byte) (n >> 56 & 0xff);
return b;
}
/**
* long類型轉byte[] (小端)
*
* @param n
* @return
*/
public static byte[] longToBytesLittle(long n) {
byte[] b = new byte[8];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
b[4] = (byte) (n >> 32 & 0xff);
b[5] = (byte) (n >> 40 & 0xff);
b[6] = (byte) (n >> 48 & 0xff);
b[7] = (byte) (n >> 56 & 0xff);
return b;
}
/**
* byte[]轉long類型(小端)
*
* @param array
* @return
*/
public static long bytesToLongLittle(byte[] array) {
return ((((long) array[0] & 0xff) << 0)
| (((long) array[1] & 0xff) << 8)
| (((long) array[2] & 0xff) << 16)
| (((long) array[3] & 0xff) << 24)
| (((long) array[4] & 0xff) << 32)
| (((long) array[5] & 0xff) << 40)
| (((long) array[6] & 0xff) << 48)
| (((long) array[7] & 0xff) << 56));
}
/**
* byte[]轉long類型(大端)
*
* @param array
* @return
*/
public static long bytesToLongBig(byte[] array) {
return ((((long) array[0] & 0xff) << 56)
| (((long) array[1] & 0xff) << 48)
| (((long) array[2] & 0xff) << 40)
| (((long) array[3] & 0xff) << 32)
| (((long) array[4] & 0xff) << 24)
| (((long) array[5] & 0xff) << 16)
| (((long) array[6] & 0xff) << 8)
| (((long) array[7] & 0xff) << 0));
}
}