我正在编写一个处理大型分隔文件的 C++ 程序。
我有一个 UTF-8 csv 文件,其中包含一行带有 (emoji?) 字符 🌟 的行。它看起来像这样:
123,"james","piotrj🌟","1996-01-28"
当我在这一行调用
getline()
时,它会读取表情符号,然后停止。所以从 getline()
得到的字符串是 123,"james","piotrj
。我不确定为什么会发生这种情况。如果我不得不猜测,我使用的区域设置不正确,并且这个表情符号(或其一部分)被解读为EOF
。
我想按原样读取这一行,进行一些字符串操作,然后将其写入另一个文件。
我这里有一些示例代码:
locale loc("en_US.UTF8");
wifstream inFile;
inFile.imbue(loc);
inFile.open("MyFile.csv");
if(inFile.is_open()){
wstring str;
if (getline(inFile, str)) {
wcout << str << endl;
}
if (getline(inFile, str)) {
wcout << str << endl;
}
inFile.close();
}
此代码的输出是:
123,"james","piotrj
。第二个 if 语句主体不执行,因为第二个 getline()
没有抓取任何内容。
为了尝试一些事情,我将语言环境更改为:
locale loc = locale();
区域设置的名称是“C”,这将获取整行。该程序的输出是:
123,"james","piotrj🌟","1996-01-28"
。这是朝着正确方向迈出的一步,但如果没有正确的区域设置,wstring 将无法正确存储它。在我的程序中,我做了一些单独的字符检查,看看该字符串是否可以用 ANSI 表示,因此我真的希望 wstring 将该表情符号作为一个字符。
我想说一下我对
getline()
和iostream
的个人看法。我希望它可以防止您和其他人犯错误并在生产代码中使用它。在使用 C++ 30 多年后,我得出的结论是,与 C 的严格规则相比,iostream 是为 C++ 中的任何操作符分配任何操作的可能性的鲜明证明。这是一个很好的例子,可以放入本书的第一页:
cout<<"Hello, world\n";
它仍然是 C++ 语言,但它 1) 非常慢,2) 它不会抛出异常,并且需要在每个 << or >> 之后进行错误检查,程序员通常不会这样做,因为所有示例都有很多 << in one line without any error checks. I would add 3) no detail documentations, because no-one interested to make detailed documentation for these classes, they are really joke classes only for demonstration purposes.
我的建议 - 如果您需要使用 IO,请使用 C stdio,它并没有过时,它由 C 程序员使用并支持,并且非常可预测。如果您需要 UTF8 和任何语言支持,请使用 ICU 库:它并不简单,但它涵盖了该领域所需的所有内容。