8

我有一个奇怪的问题,我使用

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

}

它适用于像这样的 txt 文件 http://www.speedyshare.com/files/29833132/a.txt (对不起链接,但它只有 80 个字节,所以得到它应该不是问题,如果 SO 换行符上的 ic/p 丢失)但是当我将例如水(来自http://en.wikipedia.org/wiki/UTF-16/UCS-2#Examples)添加到加载行的任何行时停止。我有错误的印象,将 wstring 作为一个输入和 wifstream 作为其他输入的 getline 可以咀嚼任何 txt 输入......有没有办法读取文件中的每一行,即使它包含时髦的字符?

4

3 回答 3

8

不太令人满意的答案是,您需要为输入流注入一个可以理解所讨论的特定字符编码的语言环境。如果您不知道选择哪个语言环境,可以使用空语言环境。

例如(未经测试):

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

不幸的是,没有标准的方法来确定给定平台可以使用哪些语言环境,更不用说根据字符编码选择一个。

上面的代码将语言环境选择交到用户手中,如果他们将其设置为合理的东西(例如en_AU.UTF-8),它可能都只是工作。

如果做不到这一点,您可能需要求助于第三方库,例如iconvICU

也与此博客条目相关(为自我推销道歉)。

于 2011-08-12T13:12:55.543 回答
4

问题在于您对全局函数的调用getline (a,line)。这需要一个std::string. 使用std::wistream::getline方法而不是getline函数。

于 2011-08-12T13:09:18.050 回答
4

C++ fstream 将 I/O 委托给它们的文件缓冲区。filebufs 总是从磁盘读取“原始字节”,然后使用流语言环境的 codecvt facet 将这些原始字节转换为它们的“内部编码”。

Awfstream是 a basic_fstream<wchar_t>,因此具有 a basic_filebuf<wchar_t>,它使用语言环境codecvt<wchar_t, char>将从磁盘读取的字节转换为wchar_ts。如果您读取 UCS-2 编码文件,则必须使用“知道”外部编码是 UCS-2 的 codecvt 执行转换。因此,您需要一个具有这种 codecvt 的语言环境(例如,参见这个 SO question

默认情况下,流的语言环境是流构造时的全局语言环境。要使用特定的语言环境,它应该是imbue()-d 在流上。

于 2011-08-12T13:12:00.563 回答