天天看點

c++讀取檔案位元組數和源檔案大小不一緻情況分析及解決1.問題2.分析fopen、_wfopen3.解決4.結論

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鍵即可彈出幫首頁面,内容詳細清晰,有很大幫助。

繼續閱讀