我正在使用需要 utf8 编码的 std::string 变量的代码。我希望能够处理用户提供的可能具有 utf-16 编码的文件(我在设计时不知道编码,但最终希望能够处理 utf8/16/32),请阅读它行逐行,并将每一行作为 utf8 编码的 std::string 转发到代码的其余部分。
我有 c++11(实际上是 c++11 的当前 MSVC 子集)和 boost 1.55.0 可以使用。我最终需要代码才能在 Linux 和 Windows 变体上工作。目前,我只是在 Windows 上使用 Visual Studio 2013 Update 4 进行原型设计,在 Windows 7 上运行。我对其他依赖项持开放态度,但他们需要有一个已建立的跨平台(即 windows 和 *nix)轨道记录,不应该是 GPL/LGPL。
我一直在假设我似乎无法找到验证方法,并且我的代码不起作用。
一个假设是,由于我最终希望这些文件中的每一行都包含在 std::string 变量中,因此我应该使用带有正确构造的 codecvt 的 std::ifstream ,以便可以将传入的 utf16 流转换为 utf8。
这个假设现实吗?我认为,另一种选择是我必须对文本文件进行一些编码检查,然后根据结果选择 wifstream/wstring 或 ifstream/string,这似乎比我开始时更没有吸引力. 当然,如果这是正确的(或唯一现实的)道路,我愿意接受。
我意识到无论如何我可能需要做一些编码检测,但现在,我不太关心编码检测部分,只关注将 utf16 文件内容转换为 utf8 std::string。
我尝试了各种不同的语言环境和编解码器组合,但都没有奏效。以下是我认为可能有效但无效的最新版本:
void
SomeRandomClass::readUtf16LeFile( const std::string& theFileName )
{
boost::locale::generator gen;
std::ifstream file( theFileName );
auto utf8Locale = gen.generate( "UTF-8" );
std::locale cvtLocale( utf8Locale,
new std::codecvt_utf8_utf16<char>() );
file.imbue( utf8Locale );
std::string line;
std::cout.imbue( utf8Locale );
for ( int i = 0; i < 3; i++ )
{
std::getline( file, line );
std::cout << line << std::endl;
}
}
我在这段代码中看到的行为是每次调用 getline() 的结果都是一个空字符串,无论文件内容如何。
如果我省略上述方法的第 3 行和第 5 行,则相同的代码在同一文件的 utf8 编码版本上可以正常工作(意味着每个 getline() 调用都返回一个正确编码的非空字符串)。
无论出于何种原因,我在 SO 或http://en.cppreference.com/或野外其他地方的任何地方都找不到任何试图做同样事情的人的例子。
欢迎所有想法/建议(符合上述要求)。