【发布时间】:2016-06-29 18:49:58
【问题描述】:
手头的任务
我在 Windows 上从 UTF-8 编码的 XML 解析文件名。我需要将该文件名传递给我无法更改的函数。它在内部使用不支持 Unicode 字符串的_fsopen()。
目前的做法
我目前的方法是将文件名转换为用户的字符集,希望文件名可以用该编码表示。然后我使用 boost::locale::conv::from_utf() 从 UTF-8 进行转换,并使用 boost::locale::util::get_system_locale() 获取当前语言环境的名称。
生活美好吗?
我在使用代码页 Windows-1252 的德语系统上,因此 get_system_locale() 正确生成 de_DE.windows-1252。如果我使用包含变音符号的文件名测试该方法,一切都会按预期工作。
问题
只是为了确保我 switched my system locale 到使用代码页 Windows-1251 的乌克兰语。在文件名中使用一些西里尔字母我的方法失败了。原因是 get_system_locale() 仍然产生 de_DE.windows-1252 现在不正确。
另一方面,GetACP() 正确地为德国语言环境生成 1252,为乌克兰语言环境生成 1251。我也知道 Boost.Locale 可以转换为给定的语言环境,因为这个小型测试程序可以按我的预期工作:
#include <boost/locale.hpp>
#include <iostream>
#include <string>
#include <windows.h>
int main()
{
std::cout << "Codepage: " << GetACP() << std::endl;
std::cout << "Boost.Locale: " << boost::locale::util::get_system_locale() << std::endl;
namespace blc = boost::locale::conv;
// Cyrillic small letter zhe -> \xe6 (ш on 1251, æ on 1252)
std::string const test1251 = blc::from_utf(std::string("\xd0\xb6"), "windows-1251");
std::cout << "1251: " << static_cast<int>(test1251.front()) << std::endl;
// Latin small letter sharp s -> \xdf (Я on 1251, ß on 1252)
auto const test1252 = blc::from_utf(std::string("\xc3\x9f"), "windows-1252");
std::cout << "1252: " << static_cast<int>(test1252.front()) << std::endl;
}
问题
如何以 Boost.Locale 支持的格式查询用户语言环境的名称?使用
std::locale("").name()会产生German_Germany.1252,使用它会导致boost::locale::conv::invalid_charset_error异常。系统区域设置是否可能保持 de_DE.windows-1252 尽管我应该将其更改为本地管理员?同样,系统语言是德语,尽管我的帐户的语言是英语。 (在我登录之前,登录屏幕是德语)
我应该坚持使用using short filenames吗?但似乎不能可靠地工作。
细则
- 编译器为 MSVC18
- Boost 是 1.56.0 版本,后端应该是 winapi
- 系统为Win7,系统语言为德语,用户语言为英语
【问题讨论】:
标签: c++ windows utf-8 codepages boost-locale