Java 編程中常會遇到須要進行字節處理的地方,本篇文章就來探討編程中會遇到的字節處理問題。編程
字節序(endianness)是對於多字節數據來講的,它描述了多字節數據存儲的順序,分爲大端字節序(big endian)和小端字節序(little endian)兩種。數組
大端序即高位字節位於低地址,而小端字節序則與之相反。例如 4 字節的數據 0x01234567
,其 大、小端字節序存儲順序以下。網絡
Big Endian編碼
address |0x100|0x101|0x102|0x103| content |01 |23 |45 |67 |
Little Endiancode
address |0x100|0x101|0x102|0x103| content |67 |45 |23 |01 |
爲保證數據在不一樣設備進行傳輸時能被正確解析,規定了使用大端字節序做爲網絡字節序。orm
因爲 Java 使用大端字節序在內存中進行數據存儲,因此進行網絡傳輸時不須要進行字節序轉換。不過除了網絡編程,仍是有須要小端字節序的狀況,下面就來討論如何進行字節序的轉換。內存
下表給出了 Java 八種基本類型的所佔的字節數,能夠看到裏面六種類型都是多字節的,而這六種在轉換時都是須要處理的。ci
類型 | 字節數 |
---|---|
byte | 1 |
boolean | 1 |
char | 2 |
short | 2 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
這裏須要強調一點,基本類型的數組形式雖是多字節的,但其字節序只和數組元素有關,而與數組元素的順序無關。例如存在短整形數組 {0x0001, 0x0002}
(Java 默認的大端字節序),則其小端字節序是 {0x0100, 0x0200}
。字符串
字節緩衝區(ByteBuffer)經常使用於數據的字節級處理,能夠利用靜態方法 ByteBuffer allocate(int)
來申請一塊固定大小的緩衝區,或者使用 ByteBuffer wrap(byte[])
包裝一個現有的字節數組。get
字節緩衝區提供了 void order(ByteOrder)
方法來設置該字節緩衝區的字節序,提供了 asTypeBuffer()
(其中 Type 爲多字節的基本類型)來將字節緩衝區做爲其餘基本類型緩衝區,以便於插入其餘基本類型,利用這些特性即可實現基本類型的字節序轉換。
下面例子利用了字節緩衝區來進行整型的字節序轉換,而只需將 asIntBuffer()
改爲相應基本類型的 asTypeBuffer()
方法,就能夠進行其它基本類型的字節序轉換。
int data = 0x01020304; ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES); buf.asIntBuffer().put(data); // [1, 2, 3, 4] System.out.println(Arrays.toString(buf.array())); buf.order(ByteOrder.LITTLE_ENDIAN); buf.asIntBuffer().put(data); // [4, 3, 2, 1] System.out.println(Arrays.toString(buf.array()));
對於基本類型的數組,只需將 data
數據改爲數組便可,以下面給出的例子。
int[] data = new int[]{0x01020304, 0x05060708}; ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES * data.length); buf.asIntBuffer().put(data); // [1, 2, 3, 4, 5, 6, 7, 8] System.out.println(Arrays.toString(buf.array())); buf.order(ByteOrder.LITTLE_ENDIAN); buf.asIntBuffer().put(data); // [4, 3, 2, 1, 8, 7, 6, 5] System.out.println(Arrays.toString(buf.array()));
Java 中字符類型使用 Unicode
字符集,因此佔用兩個字節,而字符串只須要將其轉成字符數組便可進行字節序轉換。
char[] data = new String("example").toCharArray(); ByteBuffer buf = ByteBuffer.allocate(Character.BYTES * data.length); buf.order(ByteOrder.LITTLE_ENDIAN); buf.asCharBuffer().put(data);
編程中一般須要將字符串轉字節數組,而這就涉及到字符串編解碼,但 Java 提供了很便捷的方式來進行轉換,因此無需關心如何字符串編解碼。
byte[] buf = new String("example").getBytes(); // use platform's default charset
注意上面使用了平臺的默認的字符集(可利用 Charset.defaultCharset()
獲取平臺默認字符集)進行解碼,而不是上面提到的 Unicode
字符集,但能夠以下面例子同樣指定字符集。
byte[] buf = new String("example").getBytes("UTF-8"); // use specify charset 'UTF-8'