一些基礎概念
1、1個字節有8位,7位就可以表示0-255共256種狀態,還有1位可當作符號位/特殊標識位。
2、計算機只能識別二進制,但對於人類來說,一長串的二進制交流起來很費勁,所以通過轉換成十六進制來交流。
3、轉換:0010 0001,前4位值等於2,後4位值等於1,十六進制就等於21。爲了防止誤解爲十進制數二十一,所以十六進制一般用0x前綴來表示,即0x21。
4、字符集:統一規定二進制值和字符的對應關係,就叫字符集。常見的有ASCII、GBK、Unicode。
5、字符編碼:字符集規定了某個值對應某個字符,但是並沒有規定這個值要用多少位來顯示、每一位代表什麼含義等等,字符編碼就是規定具體的編碼、解碼規則。常見的有ASCII、GBK、UTF-8/UTF-16。
ASCII
既是字符集,同時又是字符編碼。
作爲字符集,規定0-31對應特定動作(比如換行、輸出等),32-127對應字母、數字、符號等,後來又擴展了128-255對應歐洲字符。
作爲字符編碼,規定每個字符由1個字節的8位表示,最高位是校驗位,剩餘7位的值代表字符。
GBK
計算機傳到中國後,有7000多個漢字需要顯示,於是就誕生了GBK。同樣,既是字符集,有是字符編碼。
作爲字符集,規定0-127與ASCII一樣,127以上的值,分別對應中文、全角標點、羅馬字符、日文片假名等等。
作爲字符編碼,ASCII的字符用1個字節表示,中文用2個字節表示。如果要表示英文,就用1個字節,跟ASCII一樣;如果要表示中文,就用兩個字節,前一個字節範圍0xA1~0xF7,後一個字節範圍0xA1~0xFE。所以,當計算機讀到一個字節的值小於127(0X7F)時,就知道這是一個單字節字符,讀到一個字節的值大於0xA1時,就認爲這是一箇中文字符的第一個字節。
Unicode
美國有ASCII字符集、中國有GBK字符集、日本臺灣等其它國家地區也用自己的字符集,各個字符集之間不能兼容,導致各種不方便,於是誕生了全球統一的字符集Unicode。Unicode收錄了全球的字符,任何字符在Unicode字符集中都能找到對應的值。
UTF-32、UTF-16編碼
UTF32編碼規定每個字符用4個字節共32位來表示,這樣很方便,但有個缺點是浪費空間。
UTF-16規定0~65535之間的字符用2個字節表示,包含了絕大多數字符;65535以上的字符需要一些特殊規則處理,通過4個字節來表示,具體規則可以百度。
UTF-8
000000-00007F之間的字符,用0xxxxxxx表示。0是標識位,xxxxxxx部分表示數值;
000080-0007FF之間的字符,用110xxxxx10xxxxxx表示。110、10是標識位,x部分表示數值,解碼時,把x部分按順序連起來,當成二進制值就行了;
000800-00FFFF之間的字符,用1110xxxx 10xxxxxx 10xxxxxx表示;
010000-10FFFF之間的字符,用11110xxx10xxxxxx10xxxxxx10xxxxxx表示。
Emoji
emoji的字符集有很多版本,所以不統一,下面有個過濾emoji的方法。
過濾emoji,通過for循環,判斷String裏的每一位char是否在emoji區間:
private static boolean isEmojiCharacter(char codePoint) {
return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) || (codePoint == 0xD)
|| ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
|| ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
}