閱讀396 返回首頁    go 技術社區[雲棲]


Java I/O : Java中的進製詳解

一、引子

在Java世界裏,99%的工作都是處理這高層。那麼二進製,字節碼這些會在哪裏用到呢?

自問自答:在跨平台的時候,就凸顯神功了。比如說文件讀寫數據通信,還有Java編譯後的字節碼文件。下麵會有個數據通信的例子哦。

Java對對象實現Serializablle接口,就可以將其轉化為一係列字節,而在通信中,不必要關係數據如何在不同機器表示和字節的順序。這裏泥瓦匠對Serializablle接口,不做詳細講解,以後單獨詳解。

 

二、Java進製轉換

首先認識下Java中的數據類型

1、Int整型:byte(8位,-128~127)、short(16位)、int(32位)、long(64位)

2、Float型:float(32位)、double(64位)

2、char字符:unicode字符(16位)

也就是說,一個int等價於長度為4的字節數組。

Java中進製如何轉換呢?

在Java中,Int整形以及char字符型被包裝的類中提供了一係列的操作方法。比如 java.lang.Integer api如圖所示

QQ截圖20150613210316

下麵泥瓦匠寫個demo,驗證下。

package javaBasic.oi.byteoper;

public class IntegerOper
{
	public static void main(String[] args)
	{
		System.out.println("17的十六進製: " + Integer.toHexString(17));
		System.out.println("17的八進製:     " 	+ Integer.toOctalString(17));
		System.out.println("17的二進製:     " 	+ Integer.toBinaryString(17));

		System.out.println(Integer.valueOf("11", 16));
		System.out.println(Integer.valueOf("21", 8));
		System.out.println(Integer.valueOf("00010001", 2));
	}
}

右鍵Run一下,我們可以在控製台中看到如下輸出:

17的十六進製: 11
17的八進製:   21
17的二進製:   10001
17
17
17

補充:如果值太大,則需要調用 java.lang.Long 提供的方法。

 

三、Java基本類型和字節神奇轉換

這裏泥瓦匠想到了自己是個學生,典型的OO思想。那學號:1206010035是整型,怎麼轉成字節呢,上麵說的擁有字節碼的對象能通信。所以,學校關於學號這個都是這樣的方式通信的。因此,要將學號轉成字節碼才行。

泥瓦匠就寫了個工具類 IntegerConvert.java:

package javaBasic.oi.byteoper;

public class IntegerConvert
{
	/**
	 * Int轉字節數組
	 */
	public static byte[] int2Bytes(int inta)
	{
		// 32位Int可存於長度為4的字節數組 
		byte[] bytes = new byte[4];
		for (int i = 0; i < bytes.length; i++)
			bytes[i] = (byte)(int)((inta >> i * 8) & 0xff);// 移位和清零
		
		return bytes;
	}
	
	/**
	 * 字節數組轉Int
	 */
	public static int bytes2Int(byte[] bytes)
	{
		int inta = 0;
		for (int i = 0; i < bytes.length; i++)
			inta += (int)((bytes[i] & 0xff) << i * 8);// 移位和清零
		
		return inta;
	}
	
	public static void main(String[] args)
	{
		// 將我的學號轉換成字節碼
		byte[] bytes = IntegerConvert.int2Bytes(1206010035);
		System.out.println(bytes[0] + " " + bytes[1] + " " + bytes[2] + " " + bytes[3]);
		// 字節碼就可以轉換回學號
		System.out.println(IntegerConvert.bytes2Int(bytes));
	}

}

跑一下,右鍵Run,可以看到以下輸出:

-77 64 -30 71
1206010035

代碼詳細解釋如下:

1、(inta >> i * 8) & 0xff

移位 清零從左往右,按8位獲取1字節

2、這裏使用的是小端法。地位字節放在內存低地址端,即該值的起始地址。補充:32位中分大端模式(PPC)和小段端模式(x86)。

 

自然,Long也有其轉換方法,如下:

public class LongConvert
{
	/**
	 * long 轉 byte數組
	 */
	public static byte[] long2Bytes(long longa)
	{
		byte[] bytes = new byte[8];
		for (int i = 0; i < bytes.length; i++)
			bytes[i] = (byte)(long)(((longa) >> i * 8) & 0xff); // 移位和清零
		
		return bytes;
	}
	
	/**
	 * byte數組 轉 long
	 */
	public static long bytes2Long(byte[] bytes)
	{
		long longa = 0;
		for (int i = 0; i < bytes.length; i++)
			longa += (long)((bytes[i] & 0xff) << i * 8); // 移位和清零
		
		return longa;
	}
	
}

 

那字符串,字符數組呢?比如泥瓦匠的名字:李強強

Java也提供了一係列的方法,其實 java.lang.String 封裝了char[],其中本質還是對char數組的操作。代碼如下:

package javaBasic.oi.byteoper;

public class StringConvert
{
	public static void main(String[] args)
	{
		String str = "李強強";
		byte[] bytes = str.getBytes();
		// 打印字節數組
		System.out.println("'李強強'的字節數組為:");
		for (int i = 0; i < bytes.length; i++)
			System.out.print("\t" + bytes[i]);
	}
}

右鍵Run一下,可以看到以下輸出:

'李強強'的字節數組為:
	-64	-18	-57	-65	-57	-65

論證:這裏我們論證了一個中文,需要兩個字節表示,也就是說一個中文是16位

 

四、淺談Java通信中的數據

下麵簡單把泥瓦匠學生的故事延續。socket

如圖,庫表中一個學生對象,有個屬性是學號。這時候客戶端要向服務端發送這個對象。過程如下:

1、對象實現Serializable接口。

實現了Serializable接口的對象,可將它們轉換成一係列字節,並可在以後完全恢複回原來的樣子。

2、其學號屬性值 1206010035,由客戶端轉換為字節碼。

3、字節碼傳輸至服務端

4、服務端接收並轉換為對象屬性值。

 

五、總結

此文講的點有點多,泥瓦匠就想把這塊用到的知識點串起來,然後慢慢每個講解。總結如下:

1、Java中進製轉換是什麼?

2、Java中進製轉換的作用?

 

最後更新:2017-05-22 16:01:36

  上一篇:go  機器學習自主解決安全威脅離我們還有多遠?
  下一篇:go  JAVA麵試題100問第一部分