我正在处理(我希望)UTF-8文本巨大的文件。我可以使用Ubuntu 13.10(3.11.0-14-generic)和12.04复制它。
在调查错误时,我遇到了奇怪的行为
$ export LC_ALL=en_US.UTF-8
$ sort part-r-00000 | uniq -d
ɥ ɨ ɞ ɧ 251
ɨ ɡ ɞ ɭ ɯ 291
ɢ ɫ ɬ ɜ 301
ɪ ɳ 475
ʈ ʂ 565
$ export LC_ALL=C
$ sort part-r-00000 | uniq -d
$ # no duplicates found
当运行使用来读取文件的自定义C
++程序时,重复项也会出现
std::stringstream
-由于使用
en_US.UTF-8
区域设置时重复项而导致失败。
至少对于std::string
输入和输出,C ++似乎并不受影响。
为什么在使用UTF-8语言环境时发现重复项,而在C语言环境中找不到重复项?
语言环境对导致此行为的文本进行了哪些转换?
编辑:这是一个小例子
$ uniq -D duplicates.small.nfc
ɢ ɦ ɟ ɧ ɹ 224
ɬ ɨ ɜ ɪ ɟ 224
ɥ ɨ ɞ ɧ 251
ɯ ɭ ɱ ɪ 251
ɨ ɡ ɞ ɭ ɯ 291
ɬ ɨ ɢ ɦ ɟ 291
ɢ ɫ ɬ ɜ 301
ɧ ɤ ɭ ɪ 301
ɹ ɣ ɫ ɬ 301
ɪ ɳ 475
ͳ ͽ 475
ʈ ʂ 565
ˈ ϡ 565
locale
问题出现时的输出:
$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=de_DE.UTF-8
LC_TIME=de_DE.UTF-8
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=de_DE.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=de_DE.UTF-8
LC_NAME=de_DE.UTF-8
LC_ADDRESS=de_DE.UTF-8
LC_TELEPHONE=de_DE.UTF-8
LC_MEASUREMENT=de_DE.UTF-8
LC_IDENTIFICATION=de_DE.UTF-8
LC_ALL=
编辑:规范化后使用:
cat duplicates | uconv -f utf8 -t utf8 -x nfc > duplicates.nfc
我仍然得到相同的结果
编辑:文件根据iconv
-(从此处开始)是有效的UTF-8
$ iconv -f UTF-8 duplicates -o /dev/null
$ echo $?
0
编辑:看起来与此类似:http :
//xahlee.info/comp/unix_uniq_unicode_bug.html
和 https://lists.gnu.org/archive/html/bug-
coreutils/2012-07/msg00072.html
它在FreeBSD上工作
我将问题归结为strcoll()
函数问题,该问题与Unicode规范化无关。回顾:我的最小示例展示了uniq
依赖当前语言环境的不同行为:
$ echo -e "\xc9\xa2\n\xc9\xac" > test.txt
$ cat test.txt
ɢ
ɬ
$ LC_COLLATE=C uniq -D test.txt
$ LC_COLLATE=en_US.UTF-8 uniq -D test.txt
ɢ
ɬ
显然,如果语言环境是en_US.UTF-8
uniq
对待ɢ
并ɬ
作为重复项,则情况并非如此。然后,我再次使用运行相同的命令,valgrind
并使用来调查了两个调用图kcachegrind
。
$ LC_COLLATE=C valgrind --tool=callgrind uniq -D test.txt
$ LC_COLLATE=en_US.UTF-8 valgrind --tool=callgrind uniq -D test.txt
$ kcachegrind callgrind.out.5754 &
$ kcachegrind callgrind.out.5763 &
唯一的区别是,与该版本LC_COLLATE=en_US.UTF-8
名为strcoll()
而LC_COLLATE=C
没有这样做。因此,我提出了以下最小示例strcoll()
:
#include <iostream>
#include <cstring>
#include <clocale>
int main()
{
const char* s1 = "\xc9\xa2";
const char* s2 = "\xc9\xac";
std::cout << s1 << std::endl;
std::cout << s2 << std::endl;
std::setlocale(LC_COLLATE, "en_US.UTF-8");
std::cout << std::strcoll(s1, s2) << std::endl;
std::cout << std::strcmp(s1, s2) << std::endl;
std::setlocale(LC_COLLATE, "C");
std::cout << std::strcoll(s1, s2) << std::endl;
std::cout << std::strcmp(s1, s2) << std::endl;
std::cout << std::endl;
s1 = "\xa2";
s2 = "\xac";
std::cout << s1 << std::endl;
std::cout << s2 << std::endl;
std::setlocale(LC_COLLATE, "en_US.UTF-8");
std::cout << std::strcoll(s1, s2) << std::endl;
std::cout << std::strcmp(s1, s2) << std::endl;
std::setlocale(LC_COLLATE, "C");
std::cout << std::strcoll(s1, s2) << std::endl;
std::cout << std::strcmp(s1, s2) << std::endl;
}
输出:
ɢ
ɬ
0
-1
-10
-1
�
�
0
-1
-10
-1
那么,这怎么了?为什么对两个不同的字符strcoll()
返回0
(等于)?
我有以下问题: 我想以编程方式更改我的应用程序的语言。 所以我使用共享首选项来更改语言环境。 b0是保存的本地。 b0与德语语言环境de和英语语言环境en完美配合,但与美国语言环境en\U US却没有配合 当然,我添加了一个新文件夹: 使用美国字符串xml。 如果我将手机语言更改为英语(美国),应用程序将以美国英语开始。 我甚至编辑了我的台词: 仍然不工作。 “en\u US”有什么问题吗? ht
问题内容: 我有一个Action类,我想获取应用程序的语言环境并在此处进行更改,但是我不知道怎么做,也找不到答案。 我可以使用获取当前的语言环境 但是我不知道如何 设置语言环境 。 我想在上述Action类中直接为我的应用更改语言环境。我怎样才能做到这一点? 问题答案: 使用和将其放在HTTP会话中 。
问题内容: 我在指定语言代码的应用程序中读取了一个文件: 必须采用以下格式:例如 en_UK,en_US等。是否可以在继续之前验证语言环境字符串是否有效? 问题答案: 现在我要做: 效果很好。
在我的应用程序中,用户应该能够切换区域设置(用于在页面上呈现文本的语言)。大量教程使用FacesContext.get货币实例()。getViewRoot()。setLocale()。例如:http://www.mkyong.com/jsf2/jsf-2-internationalization-example/.但是,这在JSF 2.0中根本不起作用(它在1.2中确实起作用)。这种语言从不切换。
变量是计算机系统用于保存可变值的数据类型,我们可以直接通过变量名称来提取到对应的变量值。在 Linux 系统中,环境变量是用来定义系统运行环境的一些参数,比如每个用户不同的家目录(HOME)、邮件存放位置(MAIL)等。 值得一提的是,Linux 系统中环境变量的名称一般都是大写的,这是一种约定俗成的规范。 我们可以使用 env 命令来查看到 Linux 系统中所有的环境变量,执行命令如下: [r
问题内容: 我有一个Spring应用程序,希望用户能够更改首选语言环境。当前,用户可以更改当前会话的语言环境,但是我希望能够保存users选项,以便每当他们登录时,使用已保存的语言环境(如果存在)。我有一个mysql数据库,用于存储用户区域设置首选项。我创建了一个自定义AuthenticationSuccessHandler,以处理将语言环境更改为已保存的语言环境的操作,该方法适用于已将语言环境保