1.問題
最近在幫别人調試了一個問題:
- 使用此方式擷取檔案大小,
struct _stat info;
_stat(filepath, &info);
int size = info.st_size;
- 使用fopen方式擷取檔案内容,
- 最後發現擷取的位元組數和第一步取得的位元組數不一緻,相對要小一些!
這是為什麼呢?
2.分析
首先用軟體打開源檔案,發現是80個位元組,和第一步擷取的檔案位元組數一緻,而第二步擷取檔案内容得到的位元組數要少一些,記得是72個位元組;
那麼問題應該出在了第二步fopen那裡,好吧,滑鼠放在fopen上面按鍵F1,跳出微軟的幫首頁面,仔細愁一愁用法說明和示例~
fopen、_wfopen
VC2005中fopen的ccs=UNICODE實測<zt> + UTF8 如何轉變為 ansi
簡單總結下關鍵資訊:
- fopen時候需要mode參數,即以什麼配置/模式打開檔案;
- 預設情況下,使用ANSI編碼頁解釋窄檔案名字元串;
- 使用UNICODE, UTF-8, 或 UTF-16LE等Unicode模式打開檔案時,将會對讀取到的内容進行轉換成目标格式;也意味着轉換後位元組與原始位元組很可能不一樣;
- 讀或寫存儲為UTF-8編碼格式的資料時,用文本模式或者二進制模式替代Unicode模式,你得為任何編碼轉換負責。
Encodings Used Based on ccs Flag and BOM
Encodings Used Based on ccs Flag and BOM
ccs flag No BOM (or new file) BOM: UTF-8 BOM: UTF-16 UNICODE UTF-16LE UTF-8 UTF-16LE UTF-8 UTF-8 UTF-8 UTF-16LE UTF-16LE UTF-16LE UTF-8 UTF-16LE
mode modifier Translation mode t Open in text (translated) mode. b Open in binary (untranslated) mode; translations involving carriage-return and line feed characters are suppressed.
以unicode、t模式打開檔案,會進行位元組轉換,轉換後的位元組數和原始位元組數很可能不一樣,如果要讀取内容,要開啟b(Open in binary)模式,
如果源檔案是UTF-8編碼的(其實不管什麼編碼格式檔案),fopen時開啟rb(read mode and open in binary)即可。
3.解決
3.1.解決此問題
fopen時開啟rb(read mode and open in binary)即可讀取原始内容,讀到的位元組數和原始位元組數一緻;
3.2.其他方案
也可以使用其他方式讀取檔案内容,參考如下,
wstring path = GetJsonFileName();
ifstream ifstream(path);
if (ifstream.fail())
return false;
stringstream buffer;
buffer << ifstream.rdbuf();
string contents(buffer.str());
ifstream.close();
當然還有其他方式,可自行搜尋。
4.結論
出現上述問題是因為讀取檔案時因為開啟了特定模式,對原始位元組流進行了轉換,導緻轉換後的位元組數與原始檔案位元組數不一緻,
如果已經确定要打開檔案的編碼格式(可以預先約定),那麼隻要開發rb模式即可讀取原始内容。
另外遇到問題一般光标放在要了解的接口上F1鍵即可彈出幫首頁面,内容詳細清晰,有很大幫助。