小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

UTF-8, UTF-16, UTF-16LE, UTF-16BE的區(qū)別

 oskycar 2011-12-15
UTF-8, UTF-16, UTF-16LE, UTF-16BE的區(qū)別

最近遇到的麻煩事
charset里的問題, 一般我們都用unicode來作為統(tǒng)一編碼, 但unicode也有多種表現(xiàn)形式

首先, 我們說的unicode, 其實就是utf-16, 但最通用的卻是utf-8,
原因: 我猜大概是英文占的比例比較大, 這樣utf-8的存儲優(yōu)勢比較明顯, 因為utf-16是固定16位的(雙字節(jié)), 而utf-8則是看情況而定, 即可變長度, 常規(guī)的128個ASCII只需要8位(單字節(jié)), 而漢字需要24位

UTF-16, UTF-16LE, UTF-16BE, 及其區(qū)別BOM
同樣都是unicode, 為什么要搞3種這么麻煩?
先說UTF-16BE (big endian), 比較好理解的, 俗稱大頭
比如說char 'a', ascii為
0x61, 那么它的utf-8, 則為 [0x61], 但utf-16是16位的, 所以為[0x00, 0x61]
再說UTF-16LE(little endian), 俗稱小頭, 這個是比較常用的
還是char 'a', 它的代碼卻反過來: [0x61, 0x00], 據(jù)說是為了提高速度而迎合CPU的胃口, CPU就是這到倒著吃數(shù)據(jù)的, 這里面有匯編的知識, 不多說
然后說UTF-16, 要從代碼里自動判斷一個文件到底是UTF-16LE還是BE, 對于單純的英文字符來說還比較好辦, 但要有特殊字符, 圖形符號, 漢字, 法文, 俄語, 火星語之類的話, 相信各位都很頭痛吧, 所以, unicode組織引入了BOM的概念, 即byte order mark, 顧名思義, 就是表名這個文件到底是LE還是BE的,
其方法就是, 在UTF-16文件的頭2個字節(jié)里做個標記: LE [0xFF, 0xFE], BE [0xFE, 0xFF]

理解了這個后, 在java里遇到utf-16還是會遇到麻煩, 因為要在文件里面單獨判斷頭2個再字節(jié)是很不流暢的

小結:
Java代碼 復制代碼 收藏代碼
  1. InputStreamReader reader=new InputStreamReader(fin, charset)  

1. 如果這個UTF-16文件里帶有BOM的話, charset就用"UTF-16", java會自動根據(jù)BOM判斷LE還是BE, 如果你在這里指定了"UTF-16LE"或"UTF-16BE"的話, 猜錯了會生成亂七八糟的文件, 哪怕猜對了, java也會把頭2個字節(jié)當成文本輸出給你而不會略過去, 因為[FF FE]或[FE FF]這2個代碼沒有內容, 所以, windows會用"?"代替給你
2. 如果這個UTF-16文件里不帶BOM的話, 則charset就要用"UTF-16LE"或"UTF-16BE"來指定LE還是BE的編碼方式


另外, UTF-8也有BOM的, [0xEF, 0xBB, 0xBF], 但可有可無, 但用windows的notepad另存為時會自動幫你加上這個, 而很多非windows平臺的UTF8文件又沒有這個BOM, 真是難為我們這些程序員啊

錯誤的例子
1. 文件A, UTF16格式, 帶BOM LE,
InputStreamReader reader=new InputStreamReader(fin, "utf-16le")
會多輸出一個"?"在第一個字節(jié), 原因: java沒有把頭2位當成BOM

2. 文件A, UTF16格式, 帶BOM LE,
InputStreamReader reader=new InputStreamReader(fin, "utf-16be")
會出亂碼, 原因: 字節(jié)的高低位弄反了, 'a' 在文件里 [0x61, 0x00], 但java以為'a'應該是[0x00 0x61]

3. 文件A, UTF16格式, 帶BOM BE,
InputStreamReader reader=new InputStreamReader(fin, "utf-16le")
會出亂碼, 原因: 字節(jié)的高低位弄反了, 'a' 在文件里 [0x00, 0x61], 但java以為'a'應該是[0x61 0x00]

4. 文件A, UTF16格式, 帶BOM BE,
InputStreamReader reader=new InputStreamReader(fin, "utf-16be")
會多輸出一個"?"在第一個字節(jié), 原因: java沒有把頭2位當成BOM

5. 文件A, UTF16格式, LE 不帶BOM,
InputStreamReader reader=new InputStreamReader(fin, "utf-16")
會出亂碼, 因為utf-16對于java來說, 默認為be(1.6JDK, 以后的說不準)
但windows的notepad打開正常, 因為notepad默認為le, - -#

6. 文件A, UTF16格式, BE 不帶BOM,
InputStreamReader reader=new InputStreamReader(fin, "utf-16")
恭喜你, 蒙對了
但winodws的notepad打開時, 每個字符中間都多了一個" ", 因為notepad把它當成ASNI了

在windows下輸出unicode文件
通過java出來unicode文件, 也容易混淆

Java代碼 復制代碼 收藏代碼
  1. FileOutputStream fout=new FileOutputStream(file);   
  2. OutputStreamWriter writer=new OutputStreamWriter(fout, charset);  


1. charset為"UTF-16"時, java會默認添加BOM [0xFE, 0xFF], 并以BE的格式編寫byte
2. charset為"UTF-16BE"時, java不會添加BOM, 但編碼方式為 BE
3. charset為"UTF-16LE"時, java不會添加BOM, 但編碼方式為 LE

以上通過 test.getByte("utf-16"), test.getByte("utf-16be"), test.getByte("utf-16le") 可以驗證

而windows的notepad默認的unicode為 LE, 并帶BOM,
所以, 推薦輸出 UTF-16LE, 并人為添加BOM, 即:
Java代碼 復制代碼 收藏代碼
  1. byte[] bom={-1, -2};    //FF FE, java的byte用的是補碼, 驗證: b=127, b+=1, 而b=-128   
  2. fout.write(bom); 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多