2011-08-12 37 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。