2011-08-12 66 views
4

我有一個奇怪的問題, 我用問題與函數getline和「奇怪的字符」

wifstream a("a.txt"); 
wstring line; 
while (a.good()) //!a.eof() not helping 
{ 
    getline (a,line); 
     //... 
    wcout<<line<<endl; 

} 

和它工作得很好。對於這類 http://www.speedyshare.com/files/29833132/a.txt (抱歉鏈接txt文件,但它僅僅是80字節,所以它不應該是一個問題得到它,如果ic/p在SO換行丟失) 但是當我例如水(從http://en.wikipedia.org/wiki/UTF-16/UCS-2#Examples)添加到任何行是加載停止的行。我錯誤的印象是,getline將wstring作爲一個輸入,wifstream可以讓其他人咀嚼任何txt輸入... 有什麼方法可以讀取文件中的每一行,即使它包含時髦的字符?

+1

嘗試'getline '。 –

+1

由於某些原因只能匹配您的用戶名,wifstream默認爲8位字符。你必須使用std :: codecvt來告訴它識別其他的編碼。 –

+2

@ kerrek \t getline (a,line); 失敗(g ++ 4.6,linux)。順便說一句,它應該從參數中獲取模板參數? – NoSenseEtAl

回答

6

這個不太令人滿意的答案是,您需要使用能夠理解特定字符編碼的語言環境來灌注輸入流。如果您不知道要選擇哪個區域設置,則可以使用空白區域設置。

例如(未經測試):

std::wifstream a("a.txt"); 
std::locale loc(""); 
a.imbue(loc); 

不幸的是,以確定哪些語言環境,可爲指定平臺,更不用說選擇基於字符編碼一個沒有標準的方式。

上述代碼將區域設置選擇置於用戶手中,如果它們將其設置爲合理的(例如en_AU.UTF-8),它可能都適用。

如果沒有這個,您可能需要使用第三方庫,如iconvICU

此外blog entry(道歉爲自我推銷)。

+0

嗨,你的解決方案「工作」。它不會崩潰閱讀,但我仍然得到?當我嘗試着wcout的時候,真正的chars的實例... imcueing wcout does not幫助(我不知道即使它有任何意義 - 我只是:「讓我們試試...」)。現在我明白了爲什麼所有對utf 16和iostreams的仇恨...... :)仍然tnx的好回答。 – NoSenseEtAl

3

問題出在您撥打全球功能getline (a,line)。這需要std::string。使用std::wistream::getline方法而不是getline函數。

+0

也許他正在使用getline函數,因爲他想要一個字符串? wistream上的getline方法不會輸出到wstring中。 – Alastair

3

C++ fstreams刪除其文件緩衝區的I/O。 filebufs總是從磁盤讀取「原始字節」,然後使用流語言環境的codecvt facet將這些原始字節轉換爲其「內部編碼」。

wfstreambasic_fstream<wchar_t>並且因此具有basic_filebuf<wchar_t>它使用的語言環境的codecvt<wchar_t, char>從磁盤讀出的字節轉換成wchar_t秒。如果您閱讀了UCS-2編碼文件,則轉換必須由「知道」外部編碼爲UCS-2的codecvt執行。因此,您需要一個具有此類codecvt的語言環境(例如,請參見this SO question

默認情況下,流的語言環境是流構造的全局語言環境。要使用特定的區域設置,它應該是imbue() -d。