C++如何通过忽略每行的第一个字符来读取 unicode 文件

C++ how to read from unicode files by ignoring first character of each line

本文关键字:字符 第一个 读取 文件 unicode 何通过 C++      更新时间:2023-10-16

考虑一个包含 Unicode 单词的文件,如下所示

آب
آباد
آبادان

如果从右到左阅读,第一个字符是" آ"。

我的第一个要求是逐行读取文件。这很简单。

第二个要求是从每行的第二个字符逐行读取文件。 结果必须是这样的

ب
باد
بادان

如您所知,有一些解决方案,如 std::substr 来满足第二个要求,但 Afaik std::substr 不能很好地与 Unicode 字符配合使用。

我需要这样的东西

std::ifstream inFile(file_name);
//Solution for first requirement
std::string line;
if (!std::getline(inFile, line)) {
std::cout << "failed to read file " << file_name << std::endl;
inFile.close();
break;
}
line.erase(line.find_last_not_of("nr") + 1);
std::string line2;
//what should be here to meet my second requirement?
//stay on current line      
//ignore first character and std::getline(inFile, line2)) 
line2.erase(line.find_last_not_of("nr") + 1);
std::cout<<"Line= "<<line<<std::cout; //should prints آب
std::cout<<"Line2= "<<line<<std::cout; //should prints 
inFile.close();

C++11具有Unicode转换例程,但它们不是很用户友好。但是您可以使用它们制作更多用户友好的功能,如下所示:

// This should convert to whatever the system wide character encoding
// is for the platform (UTF-32/Linux - UCS-2/Windows)
std::string ws_to_utf8(std::wstring const& s)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;
std::string utf8 = cnv.to_bytes(s);
if(cnv.converted() < s.size())
throw std::runtime_error("incomplete conversion");
return utf8;
}
std::wstring utf8_to_ws(std::string const& utf8)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;
std::wstring s = cnv.from_bytes(utf8);
if(cnv.converted() < utf8.size())
throw std::runtime_error("incomplete conversion");
return s;
}
std::string remove_first_char(std::string const& utf8)
{
std::wstring ws = utf8_to_ws(utf8);
ws = ws.substr(1);
return ws_to_utf8(ws);
}
int main()
{
std::string utf8 = u8"آبادان";
std::cout << remove_first_char(utf8) << 'n';
}

输出:

بادان

通过转换为固定代码点 (UCS-2/UTF-32(,您可以使用普通字符串函数处理字符串。不过有一个警告。UCS-2并不涵盖所有语言的所有字符,因此您可能需要使用std::u32string并在UTF-8UTF-32之间编写转换函数。

这个答案有一个例子:https://stackoverflow.com/a/43302460/3807729