1. 程式人生 > >Java基礎Demo -- 基本型別轉換位元組流

Java基礎Demo -- 基本型別轉換位元組流

基本型別轉換為位元組流

位元組流轉換回基本型別

 注意理解:

0xff &0xff java移位僅支援int或long

>>帶符號右移(負數高位補1,正數高位補0),相當於除以2的n次方

>>>無符號右移(高位補0)

<<左移(低位補0),相當於乘以2的次方

/**
* ASCII碼 0x00~0x7F
* ISO8859-1/Latin-1西歐標碼
* gb2312中文簡體 16進位制範圍0xB0A1~0xF7FE unicode表示範圍\u4E00~\u9FA5 \uF900~\uFA2D
* GBK擴充的gb2312 16進位制範圍0x8140~0xFEFE
* 表示漢字的首1位bit都為1,而ASCII首1位bit為0,所以GBK編碼時,判斷是否漢字if(bytex<0)
* UTF-16LE小頭(低位為0) 中文/英文字元都是佔據兩個位元組 也叫Unicode編碼 (JVM就是處理Unicode值的) 舉例:'a' 0x6100
* UTF-16BE大頭(高位為0) 中文/英文字元都是佔據兩個位元組 也叫Unicode編碼 (JVM就是處理Unicode值的) 舉例:'a' 0x0061
* UTF-8編碼  高8位是111打頭的表示隨後的三個位元組湊在一起才是一個字元 例如中文
*                    高8位是110打頭的表示隨後的兩個位元組湊在一起才是一個字元 例如脫離ISO8859-1範圍的字元
*                    高8位的首位是0的表示單位元組的字元 例如ASCII範圍內的字元
* UTF-32編碼 每個字元都是硬性規定佔4個位元組
*/

 

/**
* ASCII碼 0x00~0x7F
* ISO8859-1/Latin-1西歐標碼
* gb2312中文簡體 16進位制範圍0xB0A1~0xF7FE(其中有5個空位是D7FA-D7FE) unicode表示範圍\u4E00~\u9FA5 \uF900~\uFA2D
* GBK擴充的gb2312 16進位制範圍0x8140~0xFEFE
* 由於表示漢字或圖形符號的“高位位元組”的首個bit都為1,而ASCII首個bit為0,而實現了這兩種字符集對ASCII的相容
* UTF-16LE小頭(低位為0) 中文/英文字元都是佔據兩個位元組 也叫Unicode編碼 (Java內部機制就是處理Unicode值的) 舉例:'a' 0x6100
* UTF-16BE大頭(高位為0) 中文/英文字元都是佔據兩個位元組 也叫Unicode編碼 (Java內部機制就是處理Unicode值的) 舉例:'a' 0x0061
* UTF-8編碼 高8位是111打頭的表示隨後的三個位元組湊在一起才是一個字元 例如中文
*           高8位是110打頭的表示隨後的兩個位元組湊在一起才是一個字元 例如脫離ISO8859-1範圍的字元
*           高8位的首位是0的表示單位元組的字元 例如ASCII範圍內的字元
* UTF-32編碼 每個字元都是硬性規定佔4個位元組
*/

/**
 * Java基本資料型別和byte陣列相互轉化的工具類
 *
 * 0xff 16進製表示法(每一個數字代表4bit) 32位在計算機內表示為 00000000 00000000 00000000 11111111 等於十進位制的255
 *
 *  << 左移運算子:運算元向左移動N位(低位補0), 相當於運算元乘以2的幾次方
 *  >> "有符號"右移運算子:運算元右移N位, 運算元為正時,高位補0 ; 運算元為正時,高位補1, 相當於運算元除以2的幾次方
 * >>> "無符號"右移運算子:運算元右移N位(高位補0)
 *
 * 對char,byte或者short進行移位處理,那麼在移位進行之前,它們會自動轉換成一個int(因為java的移位操作僅支援int位移 或者 long位移)
 *
 * 所以由此延申出的 byte的位元組移位時,為什麼要&0xff呢?其作用就是僅關心當前8bit這一位元組,其它bit位都置為零,保持二進位制補碼的一致性;
 *
 * 舉例:*				最高	 高	  稍高     最低
	255         0xff                00000000 00000000 00000000 11111111
        -1          (byte)0xff          11111111 11111111 11111111 11111111 
        1           0xff>>>7            00000000 00000000 00000000 00000001  >>>1111111
        33554431    ((byte)0xff)>>>7    00000000 00000001 11111111 11111111  >>>1111111
 *
 * &0xff 的作用:舉例 int i = (byte)( -129 & 0xff );
 * -129 32位bit補碼錶示:原碼:00000000 00000000 00000000 10000001 
 *                       求反:11111111 11111111 11111111 01111110  
 *                        加1:11111111 11111111 11111111 01111111 
 * 0xff 預設為int型別:         00000000 00000000 00000000 11111111
 * -129 & 0xff 的值為:        00000000 00000000 00000000 01111111
 * (byte)(-129&0xff)關心最低8位時:01111111
 * (byte)((-129>>8)&0xff)關心稍高8位時:11111111
 * 我們想把-129變成byte陣列儲存時,數組裡面就是[11111111],[011111111]
 * 我們想把byte陣列儲存的轉換為數值-129時,手法就是 short k = (byte[0]&0xff)<<8 | byte[1]&0xff 注意:移位操作java中僅支援int位移或long位移
 *
 * short k = (byte[0]&0xff)<<8 | byte[1]&0xff 的運算步驟
 *
 * byte[0]&0xff 運算:
 *                   第一步:byte[0]裝入記憶體,高位補1, 機器記憶體中表示為:11111111 11111111 11111111 11111111
 *                           0xff裝入記憶體,機器記憶體中表示為:           00000000 00000000 00000000 11111111
 *                           byte[0]&0xff的結果:                    00000000 00000000 00000000 11111111
 *
 *                   第二步:(byte[0]&0xff)<<8的結果:     00000000<< 00000000 00000000 11111111 00000000 最高位左移走,低位補0
 
 *                   第三步:byte[1]裝入記憶體,高位補0, 機器記憶體中表示為:00000000 00000000 00000000 01111111
 *                           0xff裝入記憶體,機器記憶體中表示為:           00000000 00000000 00000000 11111111
 *                           byte[1]&0xff的結果:                    00000000 00000000 00000000 01111111
 *
 *                   第四步:(byte[0]&0xff)<<8 | byte[1]&0xff 的運算:00000000 00000000 11111111 00000000
 *                                                                     |
 *                                                                   00000000 00000000 00000000 01111111
 *
 *                                                            結果為:00000000 00000000 11111111 01111111
 *
 *                   第五步:結果型別強轉(int->short,丟棄最高,高):short k = -129; //也就是僅用稍高位元組,最低位元組 11111111 01111111       
 */

public class ByteUtil {

	/**
	* 得到基本型別的位元組流
	* 泛型靜態方法 public static <T> T xxMethod(T t){}
	*/
	public static <T> byte[] getBytes(T t){

		byte[] bytes = null ;

		if( (t instanceof Short)){

			short s = ((Short)t).shortValue();
			bytes = new byte[2];
			bytes[0] = (byte) (s);
			bytes[1] = (byte) (s>>8); 
		}
		else if(t instanceof Integer){

			int i = ((Integer)t).intValue();
			bytes = new byte[4];
			bytes[0] = (byte) (i);
			bytes[1] = (byte) (i>>8);
			bytes[2] = (byte) (i>>2*8);
			bytes[3] = (byte) (i>>3*8);			
		}
		else if(t instanceof Long){

			long l = ((Long)t).longValue();
			bytes = new byte[8];
			bytes[0] = (byte) (l);
			bytes[1] = (byte) (l>>8);
			bytes[2] = (byte) (l>>2*8);
			bytes[3] = (byte) (l>>3*8);
			bytes[4] = (byte) (l>>4*8);
			bytes[5] = (byte) (l>>5*8);
			bytes[6] = (byte) (l>>6*8);
			bytes[7] = (byte) (l>>7*8);
		}
		else if(t instanceof Float){

			int f = Float.floatToIntBits((Float)t);
			bytes = new byte[4];
			bytes[0] = (byte) (f);
			bytes[1] = (byte) (f>>8);
			bytes[2] = (byte) (f>>2*8);
			bytes[3] = (byte) (f>>3*8);			
		}
		else if(t instanceof Double){

			long d = Double.doubleToLongBits((Double)t);
			bytes = new byte[8];
			bytes[0] = (byte) (d);
			bytes[1] = (byte) (d>>8);
			bytes[2] = (byte) (d>>2*8);
			bytes[3] = (byte) (d>>3*8);
			bytes[4] = (byte) (d>>4*8);
			bytes[5] = (byte) (d>>5*8);
			bytes[6] = (byte) (d>>6*8);
			bytes[7] = (byte) (d>>7*8);
		}
		else if(t instanceof Character){
			char c = ((Character)t).charValue();
			bytes = new byte[2];
			bytes[0] = (byte) (c);
			bytes[1] = (byte) (c>>8); 
		}

		return bytes;
	}

	/**
	* 從位元組流中獲取基本型別的值
	*/
	public static <T> T getValue(byte[] bytes, Class<T> clazz ) {

		T rtnObj = null;

		if (clazz.equals(java.lang.Character.class)){

			rtnObj = (T)Character.valueOf((char)((bytes[1]&0xff) << 8 | (bytes[0]&0xff)));
		}
		else if (clazz.equals(java.lang.Short.class)){

			rtnObj = (T)(Short.valueOf((short)( (bytes[1]&0xff) << 8 | (bytes[0]&0xff) )));
		}
		else if (clazz.equals(java.lang.Integer.class)){

			rtnObj = (T)(Object)(  (bytes[3]&0xff) << 8*3 
								 | (bytes[2]&0xff) << 8*2
								 | (bytes[1]&0xff) << 8 
								 | (bytes[0]&0xff) 
				                );
		}
		else if (clazz.equals(java.lang.Long.class)){

			rtnObj = (T)(Object)(  (bytes[7]&0xffL) << 8*7 
								 | (bytes[6]&0xffL) << 8*6
								 | (bytes[5]&0xffL) << 8*5 
								 | (bytes[4]&0xffL) << 8*4
								 | (bytes[3]&0xffL) << 8*3 
								 | (bytes[2]&0xffL) << 8*2
								 | (bytes[1]&0xffL) << 8 
								 | (bytes[0]&0xffL) 
				                );
		}
		else if (clazz.equals(java.lang.Float.class)){

			int intBit = (  (bytes[3]&0xff) << 8*3 
						  | (bytes[2]&0xff) << 8*2
						  | (bytes[1]&0xff) << 8 
						  | (bytes[0]&0xff) 
						 );
			rtnObj = (T)(Object)Float.intBitsToFloat(intBit);
		}
		else if (clazz.equals(java.lang.Double.class)){

			long longBit = (   (bytes[7]&0xffL) << 8*7 
							 | (bytes[6]&0xffL) << 8*6
							 | (bytes[5]&0xffL) << 8*5 
							 | (bytes[4]&0xffL) << 8*4
							 | (bytes[3]&0xffL) << 8*3 
							 | (bytes[2]&0xffL) << 8*2
							 | (bytes[1]&0xffL) << 8 
							 | (bytes[0]&0xffL) 
							);
			rtnObj = (T)(Object)Double.longBitsToDouble(longBit);
		}		

		return rtnObj ;
	}


	public static void unicode(){
		String str1 = "中文測試";
		byte[] ch = new byte[100];
		try {
			ch = str1.getBytes("unicode");
			System.out.println(str1+" length:"+ch.length+" unicode: "+byte2hex(ch));
			ch = str1.getBytes("utf-16");
			System.out.println(str1+" length:"+ch.length+" utf-16: "+byte2hex(ch));
			//ch = str1.getBytes("UTF-16LE");
			//System.out.println(str1+" length:"+ch.length+" UTF-16LE: "+byte2hex(ch));
			//ch = str1.getBytes("UTF-16BE");
			//System.out.println(str1+" length:"+ch.length+" UTF-16BE: "+byte2hex(ch));
			ch = str1.getBytes("utf-8");
			System.out.println(str1+" length:"+ch.length+" utf-8: "+byte2hex(ch));
			ch = str1.getBytes("utf-32");
			System.out.println(str1+" length:"+ch.length+" utf-32: "+byte2hex(ch));
			
			str1 = "test";
			ch = str1.getBytes("unicode");
			System.out.println(str1+" length:"+ch.length+" unicode:"+byte2hex(ch));
			ch = str1.getBytes("utf-8");
			System.out.println(str1+" length:"+ch.length+" utf-8:"+byte2hex(ch));
			ch = str1.getBytes("utf-16");
			System.out.println(str1+" length:"+ch.length+" utf-16:"+byte2hex(ch));
			ch = str1.getBytes("utf-32");
			System.out.println(str1+" length:"+ch.length+" utf-32:"+byte2hex(ch));

			/**
			* 編碼轉換
			*/
			String str = "中國";
			String iso88591 = new String(str.getBytes("UTF-8"), "ISO-8859-1"); //中文GBK --> UTF-8 --> ISO-8859-1
			System.out.println(iso88591); //此時列印是6個問號,因為:一箇中文UTF-8時是3個位元組,兩個中文就是6個位元組,ISO又是單位元組的字元
			str = new String(iso88591.getBytes("ISO-8859-1"), "UTF-8"); //返向的 ISO-8859-1 --> UTF-8 --> 中文GBK
			System.out.println(str);

			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String byte2hex( byte[] b) {     
	   StringBuilder s = new StringBuilder();
	   for (int i = 0; i < b.length; i++) {    
		 String hex = Integer.toHexString(b[i] & 0xFF);    
		 if (hex.length() == 1) {    
		   hex = '0' + hex;    
		 } 
		 s.append( hex.toUpperCase() );
	   }
	   return s.toString() ;
	}

	public static String bytesToHexString(byte[] src){   
		StringBuilder stringBuilder = new StringBuilder("");   
		if (src == null || src.length <= 0) {   
			return null;   
		}   
		for (int i = 0; i < src.length; i++) {   
			int v = src[i] & 0xFF;   
			String hv = Integer.toHexString(v);   
			if (hv.length() < 2) {   
				stringBuilder.append(0);   
			}   
			stringBuilder.append(hv);   
		}   
		return stringBuilder.toString();   
	}
	
	/**  
	 * Convert hex string to byte[]  
	 * @param hexString the hex string  
	 * @return byte[]  
	 */  
	public static byte[] hexStringToBytes(String hexString) {   
		if (hexString == null || hexString.equals("")) {   
			return null;   
		}   
		hexString = hexString.toUpperCase();   
		int length = hexString.length() / 2;   
		char[] hexChars = hexString.toCharArray();   
		byte[] d = new byte[length];   
		for (int i = 0; i < length; i++) {   
			int pos = i * 2;   
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));   
		}   
		return d;   
	}
	
	/**  
	 * Convert char to byte  
	 * @param c char  
	 * @return byte  
	 */  
	 private static byte charToByte(char c) {   
		return (byte) "0123456789ABCDEF".indexOf(c);   
	}  


	public static void main(String[] args) {

		char c = 'A';
		short s = -177 ;
		int i = -12345678;
		long l = -12345678900L;
		float f = -1234.567F;
		double d = -444444444.555555;

		System.out.println( getValue(getBytes(c), Character.class) );
		System.out.println( getValue(getBytes(s), Short.class) );
		System.out.println( getValue(getBytes(i), Integer.class) );
		System.out.println( getValue(getBytes(l), Long.class) );
		System.out.println( getValue(getBytes(f), Float.class) );
		System.out.printf("%f \r\n",getValue(getBytes(d),Double.class));	

		unicode();
	}
}