1. 程式人生 > >文字檔案及二進位制檔案的大小, Unicode/utf-8/ansi編碼格式

文字檔案及二進位制檔案的大小, Unicode/utf-8/ansi編碼格式

今天看別人寫的程式, 有一點不是很明白, 就是在mfc的程式中利用CFile在寫檔案時是怎麼區別二進位制檔案和文字檔案的.

首先說一下二進位制檔案和文字檔案的區別:

從網上找到一篇文章, 寫的挺基礎, 通俗易懂的, 和大家分享:

現在搞懂了文字檔案與二進位制檔案之間的關係啦.

我們可以利用二進位制編輯器檢視文字檔案.


上圖紅框中的左邊是十六進位制顯示的,右邊是文字(ascii

在程式中有這麼一句:

開始我不明白為什麼要寫兩個位元組的"fffe", 後才上網查了一下資料才發現,這與編碼方式有關.

UTF的位元組序和BOM

UTF-8以位元組為編碼單元,沒有位元組序的問題。UTF-16以兩個位元組為編碼單元,在解釋一個UTF-16文字前,首先要弄清楚每個編碼單元的位元組序。例如收到一個"奎"的Unicode編碼是594E,"乙"的Unicode編碼是4E59。如果我們收到UTF-16位元組流"594E",那麼這是"奎"還是"乙"?

Unicode規範中推薦的標記位元組順序的方法是BOM。BOM不是"Bill Of Material"的BOM表,而是Byte Order Mark。 BOM是一個有點小聰明的想法:在UCS編碼中有一個叫做"ZERO WIDTH NO-BREAK SPACE"的字元,它的編碼是FEFF。而FFFE在UCS中是不存在的字元,所以不應該出現在實際傳輸中。UCS規範建議我們在傳輸位元組流前,先傳輸 字元"ZERO WIDTH NO-BREAK SPACE"。

這樣如果接收者收到FEFF,就表明這個位元組流是Big-Endian的;如果收到FFFE,就表明這個位元組流是Little-Endian的。因此字元"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。

UTF-8不需要BOM來表明位元組順序,但可以用BOM來表明編碼方式。字元"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF。所以如果接收者收到以EF BB BF開頭的位元組流,就知道這是UTF-8編碼了。

Windows就是使用BOM來標記文字檔案的編碼方式的。

———————————————————-

好了﹐這些問題解決後﹐我們就來做單純的文字檔案的編碼識別﹐讀取與寫入測試吧。

以windows的notepad為例(其它的文字檔案讀取軟體的原理應該也差不多﹐只是會多一些特殊的判斷演算法而已)。

notepad預設有四種編碼來儲存和讀取文字檔案。分別是﹕

ANSI,Unicode,Unicode-big-endian和UTF-8。

首先來講ANSI吧﹐這個是windows作業系統在區域與語言塊設定的編碼(也就是系統預設的編碼)﹐因此像繁體作業系統就是big5,而簡體作業系統則是GBK

而Unicode和UTF-8這兩種格式相信大家已經有所瞭解(當然前者是unicode-16)

而Unicode-big-endian是什麼意思呢﹐它與Unicode幾乎一樣﹐只是它把高位放在前面(而後者則剛好相反)

上面的摘錄已經有所說明﹐這裡再解釋一下﹕

如同樣是字元"A"﹐在以下幾種格式中的儲存形式分別是﹕

UTF-16 big-endian : 00 41

UTF-16 little-endian : 41 00

UTF-32 big-endian : 00 00 00 41

UTF-32 little-endian : 41 00 00 00

好了﹐大家想一想﹐文字檔案在硬碟中是以位元組形式儲存的﹐如果不知道文字檔案的編碼﹐那是無論如何也不能正確讀出文字檔案顯示給使用者看的(亂碼了只有人才知道﹐程式則認為一切正常)

根據BOM的規則﹐因此在一段位元組流開始時﹐如果接收到以下位元組﹐則分別表明了該文字檔案的編碼。
UTF-8: EF BB BF

UTF-16 : FF FE

UTF-16 big-endian: FE FF

UTF-32 little-endian: FF FE 00 00

UTF-32 big-endian: 00 00 FE FF

而如果不是以這個開頭﹐那程式則會以ANSI,也就是系統預設編碼讀取。

位元組序:

BIG ENDIAN:最低位地址存放高位位元組,可稱高位優先,記憶體從最低地址開始按順序存放(高數位數字先寫)。最高位位元組放最前面。

LITTLE ENDIAN:最低位地址存放低位位元組,可稱低位優先,記憶體從最低地址開始按順序存放(低數位數字先寫)。最低位位元組放最前面。