編碼

參考:
字符編碼常識及問題解析
深入分析 Java 中的中文編碼問題

關(guān)于字符編碼浸踩,你所需要知道的

編碼是什么?

編碼统求,簡單的理解就是計(jì)算機(jī)中存儲數(shù)據(jù)的格式检碗;類似于現(xiàn)實(shí)世界中物質(zhì)都是由分子、原子組成码邻,在計(jì)算機(jī)中數(shù)據(jù)都是以0/1來進(jìn)行保存折剃,所以為了把0/1轉(zhuǎn)換為人類可以理解的內(nèi)容就需要編碼來進(jìn)行轉(zhuǎn)換。

單位

位(bit):0 or 1像屋;字節(jié)(byte):8個(gè)0 or 1組成怕犁。

常用編碼

ASCII(American Standard Code for Information Interchange):只支持基礎(chǔ)拉丁字符;用一個(gè)字節(jié)表示一個(gè)字符,保證最高位永遠(yuǎn)為'0'奏甫,故可以表示128個(gè)字符 碼表戈轿。
EASCII:因?yàn)闅W洲德語等語言會用到派生拉丁字符;128是不夠用的扶檐,所以就啟用了'1'開頭的另128個(gè)凶杖,'0'開頭與ASCII保存一致。
但這些對世界上其他語言漢語款筑、日語智蝠、韓語是不夠用的,需要多個(gè)字節(jié)奈梳。
GBK系列:為了解決中文編碼問題杈湾,編寫了GBK編碼集,其兼容ASCII攘须,需要注意的是不同的編碼集會存在兼容問題漆撞,GBK一個(gè)漢字使用兩個(gè)字節(jié)表示。
雖然GBK解決了中文編碼問題于宙,但是如果中國用自己開發(fā)的編碼集浮驳,日本、韓國也用自己的捞魁,這樣在信息交互時(shí)如果對方的計(jì)算機(jī)沒有對應(yīng)的編碼集解碼出的數(shù)據(jù)就是錯(cuò)誤的至会,能不能開發(fā)一套世界通用的編碼集呢,Unicode應(yīng)運(yùn)而生谱俭。
Unicode:該編碼集采用4個(gè)字節(jié)表示一個(gè)字符奉件;可以容納世界上所有的字符;但問題也很明顯昆著,假設(shè)要傳一篇英文文檔县貌,使用ASCII編碼與使用Unicode的傳輸量相差4倍,換句話說Unicode傳輸效率太低凑懂;為了解決這個(gè)問題煤痕,出現(xiàn)了UTF-8,它是Unicode的一種實(shí)現(xiàn)方式接谨。
其規(guī)則是:

  1. 單字節(jié)字符杭攻,字符第一位是0,與ASCII保持一致疤坝。
  2. 對于多字節(jié)字符(n<=4),第一個(gè)字節(jié)前n位設(shè)置為1馆铁,n+1位設(shè)置為0跑揉,其余字節(jié)前兩位設(shè)置為10。
Unicode范圍 UTF-8編碼
單字節(jié):0000 0000 - 0000 007F 0xxxxxxx
雙字節(jié):0000 0080 - 0000 07FF 110xxxxx 10xxxxxx
三字節(jié):0000 0800 - 0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
四字節(jié):0001 0000 - 001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

'王'字的Unicode編碼是'\u738B',換算成二進(jìn)制是'00000000 00000000 01110011 10001011',處于三字節(jié)范圍,使用UTF-8編碼是'1110111 10001110 10 001011'。
Unicode編碼規(guī)范下有UTF-8,UTF-16,UTF-32三種具體實(shí)現(xiàn)历谍。
UTF-32每個(gè)字符都使用4字節(jié)表示现拒。
UTF-8,采用變長技術(shù)望侈,占用1到4字節(jié)印蔬,兼容ASCII編碼,漢字占用3個(gè)字節(jié)脱衙。
UTF-16統(tǒng)一采用兩個(gè)字節(jié)表示一個(gè)字符侥猬。

java如何編碼

I/O操作中的編碼

I/O包括磁盤和網(wǎng)絡(luò)I/O,從磁盤到內(nèi)存時(shí)使用StreamDecoder來把字節(jié)轉(zhuǎn)換為字符;從內(nèi)存到磁盤時(shí)使用StreamEncoder將字符編碼成字節(jié)捐韩。

內(nèi)存中操作編碼

//String轉(zhuǎn)換到字節(jié)方法
byte[] b = str1.getBytes("UTF-8");
String s = new String(b, "UTF-8");
//Charset提供的byte[]與char[]之間的相互轉(zhuǎn)換
Charset charset = Charset.forName("UTF-8");
ByteBuffer encode = charset.encode("a");
CharBuffer decode = charset.decode(encode);
//char和byte之間的軟轉(zhuǎn)換退唠,不需要編碼和解碼,只是把一個(gè)16bit的char格式拆分為2個(gè)8bit的byte表示荤胁,僅僅是數(shù)據(jù)類型做了轉(zhuǎn)換瞧预。
ByteBuffer headByteBuffer = ByteBuffer.allocate(1024);
ByteBuffer byteBuffer = headByteBuffer.putChar('c');
String name = "hello,王若行";
//Unicode編碼:68 65 6c 6c 6f 2c 738b 82e5 884c
byte[] iso8859 = name.getBytes("ISO-8859-1");
//68 65 6c 6c 6f 2c 3f 3f 3f
//因?yàn)镮so-8859-1是單字節(jié)編碼,所以把多字節(jié)中文編碼轉(zhuǎn)換為單字節(jié)時(shí)仅政,編碼會丟失垢油,轉(zhuǎn)化為 3f(?)。
byte[] gb2312 = name.getBytes("GB2312");
//68 65 6c 6c 6f 2c cdf5 c8f4 d0d0
//GB2312字符集有一個(gè)碼表來進(jìn)行char到byte的轉(zhuǎn)換(sun.nio.cs.ext.EUC_CN類)圆丹。
byte[] gbk = name.getBytes("GBK");
//68 65 6c 6c 6f 2c cdf5 c8f4 d0d0
//GBK編碼兼容GB2312編碼滩愁。
byte[] utf16 = name.getBytes("UTF-16");
//feff 0068 0065 006c 006c 006f 002c 738b 82e5 884c
//UTF-16編碼對字符采用雙字節(jié)表示,其特點(diǎn)是編碼效率非常高运褪,規(guī)則簡單惊楼,但由于不同處理器對2字節(jié)處理方式不同(Big-endian高位字節(jié)在前,Little-endian低位字節(jié)在前)秸讹,所以需要指明是哪種檀咙,故在最前面添加2字節(jié)BYTE_ORDER_MARK值標(biāo)示。
//雖然UTF-16效率很高璃诀,但其對單字節(jié)范圍內(nèi)字符放大一倍弧可,浪費(fèi)了存儲空間,而且其不能對單個(gè)字符的編碼進(jìn)行效驗(yàn)劣欢,如果中間一個(gè)字符碼值損壞棕诵,后面的碼值都會受影響;UTF-16的特點(diǎn)決定了其只適合在計(jì)算機(jī)內(nèi)部使用,不適合作為數(shù)據(jù)傳輸編碼凿将。
byte[] utf32 = name.getBytes("UTF-32");
//00000068 00000065 0000006c 0000006c 0000006f 0000002c 0000738b 000082e5 0000884c
byte[] utf8 = name.getBytes("UTF-8");
//68 65 6c 6c 6f 2c e78e8b e88ba5 e8a18c
//UTF-8對單字節(jié)范圍內(nèi)字符用一個(gè)字符表示校套,對漢字采用三個(gè)字節(jié)表示。
//UTF-8編碼與GBK和GB2312不同牧抵,不用查碼表笛匙,所以在編碼效率上UTF-8效率更好侨把。
//UTF-8在字節(jié)效率上和編碼安全性上做了平衡,適合網(wǎng)絡(luò)傳輸和文件保存妹孙。

為什么Unicode編碼不用查碼表秋柄?
在Unicode之前,所有字符集都是和具體編碼方案綁定在一起蠢正,直接將字符和最終字節(jié)流對應(yīng)起來骇笔,類似ASCII編碼規(guī)定7bit來編碼ASCII字符集;GB2312以及GBK字符集嚣崭,限定最多2個(gè)字節(jié)來編碼字符笨触,并規(guī)定了字節(jié)序;這樣的編碼系統(tǒng)通常是簡單的查表有鹿,通過代碼頁就可以直接將字符映射為存儲設(shè)置上的字節(jié)流旭旭。
這種方法缺點(diǎn)在于,字符和字節(jié)流耦合得太緊密了葱跋,限制了字符集的擴(kuò)展能力持寄。
Unicode在設(shè)計(jì)上考慮了這一點(diǎn),將字符集和字符編碼方案分離開娱俺。
雖然每個(gè)字符在Unicode字符集中都能找到唯一確定的編號(字符碼),但是決定最終字節(jié)流的是具體字符編碼(UTF-8/UTF-16/UTF-32)稍味。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市荠卷,隨后出現(xiàn)的幾起案子模庐,更是在濱河造成了極大的恐慌,老刑警劉巖油宜,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掂碱,死亡現(xiàn)場離奇詭異,居然都是意外死亡慎冤,警方通過查閱死者的電腦和手機(jī)疼燥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚁堤,“玉大人醉者,你說我怎么就攤上這事∨” “怎么了撬即?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長呈队。 經(jīng)常有香客問我剥槐,道長,這世上最難降的妖魔是什么宪摧? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任才沧,我火速辦了婚禮迈喉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘温圆。我一直安慰自己,他們只是感情好孩革,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布岁歉。 她就那樣靜靜地躺著,像睡著了一般膝蜈。 火紅的嫁衣襯著肌膚如雪锅移。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天饱搏,我揣著相機(jī)與錄音非剃,去河邊找鬼。 笑死推沸,一個(gè)胖子當(dāng)著我的面吹牛备绽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鬓催,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼肺素,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宇驾?” 一聲冷哼從身側(cè)響起倍靡,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎课舍,沒想到半個(gè)月后塌西,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡筝尾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年捡需,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忿等。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栖忠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贸街,到底是詐尸還是另有隱情庵寞,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布薛匪,位于F島的核電站捐川,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏逸尖。R本人自食惡果不足惜古沥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一瘸右、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧岩齿,春花似錦太颤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至乞封,卻和暖如春做裙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肃晚。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工锚贱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人关串。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓拧廊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親悍缠。 傳聞我的和親對象是個(gè)殘疾皇子卦绣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 編碼問題一直困擾著開發(fā)人員,尤其在 Java 中更加明顯飞蚓,因?yàn)?Java 是跨平臺語言滤港,不同平臺之間編碼之間的切換...
    x360閱讀 2,470評論 1 20
  • 字符集和編碼簡介 在編程中常常可以見到各種字符集和編碼趴拧,包括ASCII,MBCS,Unicode等字符集溅漾。確切的說...
    蘭山小亭閱讀 8,461評論 0 13
  • 誠然,十月八號的媒體平臺都被鹿關(guān)CP逼瘋了后臺也不會影響如我這般小老百姓的生活著榴√砺模“名人”,對于更多的如我一般不追星...
    蛋殼殼閱讀 354評論 0 2
  • a.閱讀這個(gè)故事讓我想起一本書(拆掉思維里的墻)脑又,學(xué)會打破常規(guī)暮胧,摒棄原有固化的思維模式。打破邏輯局限问麸,將思維往更寬...
    周筠桐閱讀 202評論 0 0
  • 我三歲之前的人生過的什么樣严卖,我自己也后知后覺席舍,沒有概念 三歲以后的人生,多了他 一直到現(xiàn)在哮笆,我們已經(jīng)相伴而行十四年...
    Skyexin閱讀 164評論 2 0