Java基礎Demo -- 基本型別轉換位元組流
阿新 • • 發佈:2018-12-20
基本型別轉換為位元組流
位元組流轉換回基本型別
注意理解:
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(); } }