假設有一個檔案,內容包含中文,也包含 ASCII 字元(皆是可顯示字元)。
如果這個檔案格式為 UTF-8,則 ASCII 碼佔用 1 個 byte,中文字佔用 3 個 byte。且代表中文的這 3 個 byte,必定是負值。
(其他語言的文字,未必是用 3 byte 儲存,但繁體中文佔用了 3 byte,UTF-8 的特性就是 byte 數是變動的)
所以 stringstream 用 UTF-8 的 ASCII 的可顯示字元,來當作 delimiter分割字串,是很安全的,例如用 ASCII 的 "空白" 來將以下的檔案,每一行輸入都拆解成兩個獨立字串:
apple 蘋果 橘子 哈哈 兔子 rabbit
可以這樣寫:
ifstream inputFile(fileName.c_str());string a, b, line;while(getline(inputFile, line)){stringstream tkn(line);tkn >> a >> b;cout << " [Debug] a == " << a << endl;cout << " [Debug] b == " << b << endl;}inputFile.close();
輸出會是:
[Debug] a == apple [Debug] b == 蘋果 [Debug] a == 橘子 [Debug] b == 哈哈 [Debug] a == 兔子 [Debug] b == rabbit
一般我很少直接採用 Unicode 編碼來處理字串,較常採用 UTF-8 。因為 UTF-8 的前 128 個編碼,跟 ASCII 編碼是完全相同的,如此方便程式碼可以相容 ASCII 編碼,同時又可以處理寬字元。許多支持多國語言的程式,預設都用 UTF-8 就是這個緣故。
注意在 Window 系統記事本若將檔案存成 UTF-8 編碼,檔頭會多了 0xefbbbf 這 3 個 byte。因此在 Window 將檔案存成 UTF-8 時,盡量不要用記事本,改用其他的文字編輯器存(例如 Notepad++)較好。
我通常採用 string 類別直接存取 UTF-8 的字串,在 ASCII 跟寬字元共用的檔案中,string 無法判斷總共有幾個字元,它只會一個 byte 一個 byte 的存取,因此 string 的 size() 函式就失去參考作用。
在 Window 作業系統,大部分採用 UTF-16,將字元存入 wchar_t 型態內,在 Window 內 wchar_t 佔用 2 byte,在 Linux 下 wchar_t 佔用 4 byte (UTF-32)。
所以同樣採用 wchar_t 的一個程式,可能讀取檔案的編碼就會有不統一的問題。所以我覺得程式碼統一成 UTF-8,都用 char 為基底來讀字元較佳。
留言
張貼留言