Windows文本文件編碼


 

1 ANSI編碼    2

2 UTF16BE編碼    2

3 UTF16LE編碼    2

4 UTF-8編碼    2

5 BOM    3

6 亂碼    3

7 總結    5

 

 

如下圖所示,在記事本里輸入"編碼",然后另存為的時候,有四種編碼:

圖1

按下表所示,四種編碼存為四個文件:

文件名

ANSI 

A.txt 

Unicode 

U.txt 

Unicode big endian 

UB.txt 

UTF-8 

U8.txt 

使用VC++6.0Visual Studio以二進制方式打開這四個文件。二進制編碼一目了然,如下圖所示:

圖2

1 ANSI編碼

A.txt有四個字節:B1 E0 C2 EB。其中B1 E0是"編"的GBK編碼,C2 EB是"碼"的GBK編碼。

所以,記事本里的ANSI編碼,對於簡體中文操作系統而言,就是GBK編碼。對於繁體中文操作系統而言,就是Big5編碼……

2 UTF16BE編碼

UB.txt有六個字節:FE FF 7F 16 78 01。其中FE FFBOMByte Order Mark),暫時不用管它。0x7F16是"編"的Unicode編碼,0x7801是"碼"的Unicode編碼。

UTF16BE編碼是16位(2字節)的Unicode編碼,BE表示big endian,即高位字節在前,低位字節在后。Unicode編碼0x7F16的高位字節是7F,低位字節是16UTF16BE編碼就是7F 16

3 UTF16LE編碼

U.txt有六個字節:FF FE 16 7F 01 78。其中FF FEBOM,暫時不用管它。0x7F16是"編"的Unicode編碼,0x7801是"碼"的Unicode編碼。

UTF16LE編碼是16位(2字節)的Unicode編碼,LE表示little endian,即低位字節在前,高位字節在后。Unicode編碼0x7F16的高位字節是7F,低位字節是16UTF16LE編碼就是16 7F

可見:UTF16LEUTF16BE只是高低位字節交換了一下而已。

4 UTF-8編碼

U8.txt有九個字節:EF BB BF E7 BC 96 E7 A0 81。其中EF BB BFBOM,暫時不用管它。E7 BC 96是"編"的UTF-8編碼,E7 A0 81是"碼"的UTF-8編碼。

5 BOM

BOMByte Order Mark的縮寫,它用來指明編碼,如下所示:

BOM

編碼

FE FF 

UTF16BE

FF FE 

UTF16LE

EF BB BF

UTF-8 

上面的FE FFFF FE正好逆序,這也就是Byte Order Mark(字節順序標記)的來由吧。

6 亂碼

記事本通過BOM來區分各種編碼,為什么不給ANSI搞個BOM?原因在於——向下兼容。從DOSWin98,文本文件都是ANSI編碼,都沒有BOM。為了能夠順利的打開這些文件,不能增加BOM

通過BOM來區分各種編碼,是一個非常好的想法。不過,沒有歷史包袱的Linux不買賬——Linux默認就使用UTF-8編碼,而且是沒有BOMUTF-8編碼。

為了能夠打開Linux生成的沒有BOMUTF-8編碼文件,記事本在打開沒有BOM的文本文件時,會對其進行檢查。如果所有編碼符合UTF-8,就以UTF-8編碼打開。

把圖1中的"編碼"替換為"聯通",另存為ANSI編碼。再次打開,顯示如下圖所示:

圖3

使用VC++6.0打開這個文件,一切正常,如下圖所示:

圖4

記事本顯示亂碼,是因為它會把"聯通"的GBK編碼C1 AA CD A8當做UTF-8編碼進行顯示;VC++6.0沒有顯示亂碼,是因為它不支持UTF-8編碼,只支持ANSI編碼。

有哪些漢字的GBK碼會被當做UTF-8編碼呢?一段MFC代碼就讓它們原形畢露了:

CFile f;

if(f.Open(_T("W:\\1.txt"),CFile::modeCreate | CFile::modeWrite))

{

f.Write("\r\n",4); //這句很重要,否則記事本打開后顯示亂碼

int q = 0; //區碼

int w = 0; //位碼

int c = 0;

BYTE n[2]; //內碼

for(q = 0x81;q <= 0xFE;++q)

{

n[0] = q;

for(w = 0x40;w <= 0xFE;++w)

{

n[1] = w;

if(n[0] >= 0xC0 && n[0] <= 0xDF

&& n[1] >= 0x80 && n[1] <= 0xBF)

{

f.Write(n,2);

if(++c >= 40)

{

c = 0;

f.Write("\r\n",2);

}

}

}

}

f.Close();

}

運行結果如下:

圖5

這樣的漢字竟然有2048個。除了"聯通"還有如下常見的漢字:

乾坤、學習、史實、母女、孝順、魯莽、矛盾、沉默、詩詞、腳趾、拇指、農忙、投石、泰山、水簾、矢量、糧食、太平、謙遜、堯舜、一十百千

注意:上圖第一行的全角冒號很重要,就是因為它的存在,記事本才不會誤判編碼為UTF-8,也就不會亂碼顯示了。類似的字符還有很多,如下所示:

,、:;""。!……——【】■□▲△◆◇○◎●★☆←↑→↓

7 總結

Windows下,文本文件有五種編碼:ANSIUTF16BEUTF16LEUTF-8BOMUTF-8BOM(僅讀取時支持該編碼)。

另存為ANSI編碼時,因為沒有BOM,所以有可能會被記事本、UltraEdit等文本編輯器當做無BOMUTF-8編碼,導致顯示亂碼。

生成的文本文件除非要用於Win98,否則最好使用UTF-8編碼保存。

某些軟件,如:Android Studio強制要求源代碼文件使用無BOMUTF-8編碼。對於這類文件,可使用記事本查看,不要保存。否則前面三個字節的BOMEF BB BF)刪除起來還是比較麻煩的。

為了方便的在這五種編碼之間相互轉換,可參考筆者的博文:

http://blog.csdn.net/hanford/article/details/53351153


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM