【发布时间】:2016-02-10 19:10:36
【问题描述】:
在 OS X 上使用默认设置编译 Boost 1.59.0 使用 iconv 库。当使用像 boost::locale::to_upper() 这样的带有 UTF8 字符的东西时,iconv 会导致像"GRüßEN” 这样的输入结果像"grüßEN” 这样的输入。如您所见,某些字符的大写字母不正确。
我读到修复是使用 ICU 而不是 iconv,所以我开始使用 ICU 构建 Boost。对于我的用例,我遵循的方法如下:
- 下载 unix tar 球(不是 ZIP,它具有 CR/LF 行结尾并且不起作用)。解压它。
- 将文件
boost/libs/filesystem/src/operations.cpp的第1414 行的代码修改为读取# if 0,以便始终执行回退代码。否则我会收到一个链接错误,告诉您fchmodat在 OS X 10.9 中不可用。 - 在
http://site.icu-project.org/download/56#TOC-ICU4C-Download下载ICU 56.1。解压它。 - cd 到 ``icu/source```。
- 运行
./configure --enable-static --disable-shared CXXFLAGS="-std=c++14" --prefix="<path to install ICU>" - 运行
gnumake && gnumake install - cd 到
boost_1_59_0/。 - 运行
./bootstrap.sh toolset=darwin macosx-version=10.11 macosx-version-min=10.8 --with-icu=<path where icu was installed> - 运行
./b2 toolset=darwin --without-mpi optimization=speed cxxflags="-arch x86_64 -fvisibility=hidden -fvisibility-inlines-hidden -std=c++14 -stdlib=libc++ -ftemplate-depth=512" linkflags="-stdlib=libc++" --reconfigure boost.locale.iconv=off boost.locale.icu=on -sICU_PATH=<path to my icu install dir> -link=static stage。
现在这可以正确编译 Boost 库的一个版本,但在使用此版本时,boost::locale::to_upper() 现在完全跳过 UTF8 字符并返回 "GREN” 以获取 "grüßEN” 等输入。
测试代码如下:
static boolean defaultLocaleWasInitialized = false;
...
void String::p_initDefaultLocale(void)
{
boost::locale::generator gen;
std::locale defaultLocale = gen("");
std::locale::global(defaultLocale);
std::wcout.imbue(defaultLocale);
}
...
String::Pointer String::uppperCaseString(void) const
{
if (!defaultLocaleWasInitialized) {
String::p_initDefaultLocale();
defaultLocaleWasInitialized = true;
}
auto result = boost::locale::to_upper(*this);
auto newString = String::stringWith(result.c_str());
return newString;
}
...
TEST(Base_String, UpperCaseString_StringWithLowerCaseCharacters_ReturnsOneWithUpperCaseCharacters)
{
auto test = String::stringWith("Mp3 grüßEN");
auto result = test->uppperCaseString();
ASSERT_STREQ("MP3 GRÜSSEN", result->toUTF8());
}
关于我哪里出错了有什么建议吗?
【问题讨论】:
-
iconv在不同编码之间转换字符串——它不会进行大小写转换。您应该包含一个显示问题的小型测试程序的代码。 -
将代码添加到我的问题中。试图找到我在哪里读到 ICU 是正确转换所必需的。字符串是否使用您的 boost 库正确转换?
-
在字符串文字中包含非 ascii 字符,例如在
"Mp3 grüßEN"中是未定义的行为。您必须以其他方式确保您的字符串包含您希望它包含的字符,例如。通过 UTF-8 对该字符串进行编码并将生成的字节编码如下:ü →"\xc3\xbc"。您使用的任何库都必须以某种方式知道您使用的编码。 -
使用
-DU_CHARSET_IS_UTF8=1重新编译ICU。使用字符串文字"GR \xC3\xBC en"作为测试时,我得到相同的结果(跳过的字符)。 -
我不确定输入是否是问题所在。如果我复制取自stackoverflow.com/questions/22331487/… 的代码,我会得到
grüßen vs GREN gren gren
标签: macos boost unicode locale icu