文本文件的編碼識別


文本文件的編碼識別

文本文件的編碼問題,困擾我很久,在跨平台、源程序中的中文字符、從文本文件中讀取中文字符的時候,若對文件編碼問題沒有弄清楚,難免會走彎路。對此情況,我准備針對幾個主題,記錄下自己學習的心得,以備日后查閱和分享。

認識文本文件

文件分為兩種類型:文本文件和二進制文件; 
文件文件:是以字符編碼的方式進行保存的;每一行都以換行符結束(由於歷史原因,各操作系統的換行符不一樣,Windows的是"<回車><換行>",即"\r\n",Unix/Linux的是"<換行>",即"\n",Mac的是"回車",即"\r");在文件最后一行的結尾有文件結束標志EOF,它的值也依賴於系統,一般為-1。 
二進制文件:是將內存中數據原封不動的讀取和寫入文件中。

字符編碼

一般常見的編碼格式有:ASCII、UTF-8、UTF-16、GB2312、Big5、GBK、GB18030。 詳細的字符編碼知識,此處不再多說。

需要知道的事:

  • 在Windows的語境中,所謂的[ANSI]指的是對應當前系統 locale 的遺留(legacy)編碼。
  • 在Windows的語境中,所謂的[Unicode]指的是帶有 BOM 的小端序 UTF-16。
  • 在Windows的語境中,所謂的[UTF-8]指的是帶 BOM 的 UTF-8。

文件編碼的模式識別

知道了字符編碼的細節,還不足以正確處理我們所面對的種類繁多的文本文件。 
首先,我們看看各編碼格式的文件存儲格式。

BOM:要識別UTF-8和UTF-16就不得不說到字節順序標記(byte-order mark,BOM),它用來標識該字節流的字節序,是高位在前還是低位在前。從Unicode3.2開始,BOM只能位於流的開頭,只能用於標識字節序。

UTF-16中,字節順序標記被放置為文件或字符串流的第一個字符,以標示在此文件或字符串流中,以所有十六比特為單位的字碼的尾序(字節順序)。 * 如果十六比特單位被表示成大尾序,這字節順序標記字符在串行中將呈現0xFE,其后跟着0xFF(其中的0x用來標示十六進制)。 * 如果十六比特單位使用小尾序,這個字節串行為0xFF,其后接着0xFE。

UTF-8則沒有字節順序的議題。UTF-8編碼過的字節順序標記則被用來標示它是UTF-8的文件。它只用來標示一個UTF-8的文件,而不用來說明字節順序。 許多Windows程序(如記事本)會添加字節順序標記到UTF-8文件。然而,在類Unix系統(大量使用文本文件,用於文件格式,用於進程間通信)中,這種作法則不被建議采用。 故,UTF-8分為UTF-8有BOM格式和UTF-8無BOM格式。

UTF-8: 若為UTF-8有BOM格式,則文件開頭為 EF BB BF; 若為UTF-8無BOM格式,則不能依據上述規則;此時需要依據UTF-8編碼格式來判斷,其編碼如下:

U-00000000 - U-0000007F: 0xxxxxxx 
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx 
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx 
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

UTF-16: 若為UTF-16(大端序),則文件開頭為 FE FF; 若為UTF-16(小端序),則文件開頭為 FF FE;

GB2312: GB2312中對所收漢字進行了"分區"處理,每區含有94個漢字/符號。這種表示方式也稱為區位碼。

  • 01-09區為特殊符號。
  • 16-55區為一級漢字,按拼音排序。
  • 56-87區為二級漢字,按部首/筆畫 排序。

在使用GB2312的程序通常采用EUC儲存方法,以便兼容於ASCII. 
ASCII字符,范圍為0x20-0x7E,直接用單字節表示。 每個漢字及符號以兩個字節來表示。第一個字節稱為"高位字節",第二個字節稱為"低位字節"。 "高位字節"使用了0xA1-0xF7(把01-87區的區號加上0xA0),"低位字節"使用了0xA1-0xFE(把01-94加上0xA0)。

Big5: Big5碼是一套雙字節字符集,使用了雙八碼存儲方法,以兩個字節來安放一個字。第一個字節稱為"高位字節",第二個字節稱為"低位字節"。 "高位字節"使用了0x80-0xFE,"低位字節"使用了0x40-0x7E,及0xA1-0xFE。 因Big5相對使用較少,此處不做識別。

GBK: 字符有一字節和雙字節編碼,00–7F范圍內是一位,和ASCII保持一致,此范圍內嚴格上說有96個文字和32個控制符號。 
之后的雙字節中,前一字節是雙字節的第一位。總體上說第一字節的范圍是81–FE(也就是不含80和FF),第二字節的一部分領域在40–7E,其他領域在80–FE.

GB18030: 標准采用單字節、雙字節和四字節三種方式對字符編碼。 
使用0×00至0×7F碼位(對應於ASCII碼的相應碼位)。 
雙字節部分,首字節碼位從0×81至0×FE,尾字節碼位分別是0×40至0×7E和0×80至0×FE。 四字節部分采用GB/T 11383未采用的0×30到0×39作為對雙字節編碼擴充的后綴,這樣擴充的四字節編碼,其范圍為0×81308130到0×FE39FE39。其中第 一、三個字節編碼碼位均為0×81至0×FE,第二、四個字節編碼碼位均為0×30至0×39。

面向字節的模式識別

UTF-16 直接根據其BOM識別; 
UTF-8 首先根據BOM識別,若不符,再以上述編碼規則識別; 
GB2321、GB18030 因GB18030完全兼容GB2321,則只識別GB18030,根據如下規則識別:

單字節: 0到0x7F 0000.0000-0111.1111 雙字節: 第一個字節的值從0x81到0xFE,第二個字節的值從0x40到0xFE(不包括0x7F) 1000.0001-1111.1110 0100.0000-1111.1110 四字節,第一個字節的值從0x81到0xFE,第二個字節的值從0x30到0x39,第三個字節從0x81到0xFE,第四個字節從0x30到0x39 1000.0001-1111.1110 0011.0000-0011.10001 1000.0001-1111.1110 0011.0000-0011.10001

 PS:個人新干博客地址 http://www.lontoken.com/


免責聲明!

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



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