1. 程式人生 > 實用技巧 >【資料結構】- Java位元組序、主機位元組序和網路位元組序掃盲貼

【資料結構】- Java位元組序、主機位元組序和網路位元組序掃盲貼

  Java程式設計師是幸福,因為相對於C/C++的不跨平臺,JVM為我們遮蔽了大量的底層細節和複雜性,讓我們能夠將精力放在實現特定的業務邏輯上,所以使用java開發專案效率是比較高的。同時java程式設計師是悲哀的,就是因為JVM遮蔽了很多技術細節,導致java程式設計師基本功普遍較差,對一些基本概念理解不深,甚至根本沒有聽說過。作為一個java程式設計師,我深深的感到自己知識面的狹窄。無意中看到了位元組序,以前竟然都不知道,這裡記錄下,掃個盲。

使用C/C++進行網路程式設計的程式設計師,肯定會接觸到“位元組序”的概念,但是使用java進行網路程式設計,卻根本不會接觸到“位元組序”。為什麼會這樣呢?我們先從位元組序說起。位元組順序是指佔用記憶體多於一個位元組型別的資料在記憶體中的存放順序,有小端、大端兩種順序。小端位元組序(little endian):低位元組資料存放在記憶體低地址處,高位元組資料存放在記憶體高地址處;大端位元組序(bigendian):高位元組資料存放在低地址處,低位元組資料存放在高地址處。

Java中一個int型資料佔用4個位元組,假如有一個16進位制的int數,int value = 0x01020304;採用不同的位元組序,在記憶體中的儲存情況見下圖:

顯然大位元組序,是比較符合人類思維習慣的。

至於計算機到底是BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有關的,一種CPU不是BIG-ENDIAN就是LITTLE-ENDIAN。IA架構(Intel、AMD)的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola處理器是Big-Endian。這其實就是所謂的主機位元組序。而網路位元組序是指資料在網路上傳輸時是大頭還是小頭的,在Internet的網路位元組序是BIG-ENDIAN。所謂的JAVA位元組序指的是在JAVA虛擬機器中多位元組型別資料的存放順序,JAVA位元組序也是BIG-ENDIAN。可見網路和JVM都採用的是大位元組序,個人感覺就是因為這種位元組序比較符合人類的習慣。由於JVM會根據底層的作業系統和CPU自動進行位元組序的轉換,所以我們使用java進行網路程式設計,幾乎感覺不到位元組序的存在。

那麼java裡面,怎麼判斷你的計算機是大端儲存、還是小端儲存呢?JDK為我們提供一個類ByteOrder,通過以下程式碼就可以知道機器的位元組序

System.out.println(ByteOrder.nativeOrder());

在java.nio包下提供了ByteOrder、ByteBuffer等於位元組序相關的類,我們也可以改變JVM中預設的位元組序。該例子來源於
http://blog.csdn.net/veryitman/article/details/6819017

程式碼如下:

package net.aty.util;


import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.util.Arrays; public class JVMEndianTest { public static void main(String[] args) { int x = 0x01020304; ByteBuffer bb = ByteBuffer.wrap(new byte[4]); bb.asIntBuffer().put(x); String ss_before = Arrays.toString(bb.array()); System.out.println("預設位元組序 " + bb.order().toString() + "," + " 記憶體資料 " + ss_before); bb.order(ByteOrder.LITTLE_ENDIAN); bb.asIntBuffer().put(x); String ss_after = Arrays.toString(bb.array()); System.out.println("修改位元組序 " + bb.order().toString() + "," + " 記憶體資料 " + ss_after); } }

執行結果如下:
預設位元組序 BIG_ENDIAN, 記憶體資料 [1, 2, 3, 4]
修改位元組序 LITTLE_ENDIAN, 記憶體資料 [4, 3, 2, 1]