我编写了一个个人网络应用,使用charCodeAt()
将用户输入的文本转换为相关的字符代码(例如⊇
转换为8839
进行存储)然后将其发送到Perl,后者将它们发送到MySQL。要检索输入文本,应用会使用fromCharCode()
将数字转换回文本。
我选择这样做是因为Perl的unicode支持很难正确处理。所以Perl和MySQL只能看到数字,这会让生活变得更简单。
我的问题是,我可以依靠fromCharCode()
始终将8834这样的数字转换为相关字符吗?我不知道它使用什么标准,但是假设它使用UTF-8,如果将来改为使用UTF-16,如果没有向后兼容性,这显然会破坏我的程序。
我知道我对这些概念的看法并不是那么清楚,因此请注意澄清我是否表现出误解。
答案 0 :(得分:9)
fromCharCode
和toCharCode
处理Unicode 代码点,即0到65535(0xffff)之间的数字。 Unicode和代码点是永久性的,因此您可以信任它们永远保持不变。
编码(如UTF-8和UTF-16)采用代码点(数字)流并输出字节流。 JavaScript有点奇怪,因为根据UTF-16规则,BMP之外的字符必须通过两次调用toCharCode
来构造。但是,几乎你遇到的每一个角色(包括中文,日文等)都在BMP中,所以即使你不处理这些案件,你的程序也会有效。
您可以做的一件事是将数字转换回字节(以big-endian int16格式),并将结果文本解释为UTF-16。 fromCharCode
和toCharCode
的行为在当前的JavaScript实现中已得到修复,并且不会发生变化。
答案 1 :(得分:5)
我选择这样做是因为Perl的unicode支持很难正确处理。
Perl对任何主要编程语言都有最强大的Unicode支持。使用Perl比使用C,C ++ ,Java,C ♯更容易使用Unicode Python,Ruby,PHP或Javascript。这不是未受过教育的盲目忠诚的夸张和助推。基于十多年的专业经验和学习,这是一项经过深思熟虑的评估。
天真用户遇到的问题几乎总是因为他们欺骗了自己的Unicode。头号最糟糕的大脑错误认为Unicode就像ASCII,但更大。这绝对是完全错误的。正如我在别处写的那样:
从根本上和批判性不正确,Uɴɪᴄᴏᴅᴇ只是相对于ᴀsᴄɪɪ的一些放大字符集。至多,这只不过是stsᴏ-10646。 Uɴɪᴄᴏᴅᴇ包括更多,只是将字符分配给字形:校对和比较规则,三种形式的套管,非字母套管,多码点案例折叠,规范和兼容组合和分解归一化表单,序列化表单,字形集群,单词和换行符,脚本,数字等值,宽度,双向性,镜像,打印宽度,逻辑排序排除,字形变体,上下文行为,区域设置,正则表达式,多种形式的组合类,多个分解的类型,数百和数百非常有用的属性,以及更多!
是的,这很多,但它与Perl无关。它与Unicode有关。 Perl允许您在使用Unicode时访问这些内容不是错误而是功能。那些其他语言不允许您完全访问Unicode绝不能被视为对他们有利的一点:相反,这些都是最严重的严重错误,因为如果你不能工作在21世纪使用Unicode,那么这种语言对于现代文本处理的苛刻要求来说是一种原始的,破碎的,根本无用的。
Perl不是。在Perl中使用这些东西比在其他语言中做这些事情要容易多了几百倍;在大多数人中,你甚至无法开始解决他们的设计缺陷。你只是简单地搞砸了。如果某种语言不能提供完整的Unicode支持,那么它就不适合本世纪;放弃它。
在this answer中,您可以在前面找到用于在Perl中处理Unicode的七个简单步骤,在同一个答案的底部,您会发现一些有用的样板代码。理解它,然后使用它。不要接受破碎。您必须先学习Unicode才能使用Unicode。
这就是为什么没有简单的答案。 Perl使您可以轻松使用Unicode, 提供 ,您了解Unicode的真正含义。如果您正在处理外部源,那么您必须安排该源使用某种编码。
还阅读我所说的所有内容。那些是你真正需要理解的东西。另一个属于规则# 49 的破坏问题是Javascript被破坏,因为它不会以完全相同的方式处理所有有效的Unicode代码点,而与其平面无关。 Javascript几乎在所有其他方面都被打破了。它不适合Unicode工作。只有规则# 34 会杀了你,因为你无法让Javascript遵循things like \w
中定义的Unicode regexes要求的标准}。
令人惊讶的是,有多少种语言对Unicode完全没用。但Perl绝对是不其中之一!
答案 2 :(得分:4)
在我看来,不会突破。
阅读Joel Spolsky关于Unicode and character encoding的文章。本文的相关部分引用如下:
每一封信中都有 字母表分配了一个数字 这是一个Unicode联盟 写得像这样:U + 0639。这个 number被称为代码点。 U + 表示“Unicode”,数字是 十六进制。英文字母A会 是U + 0041。
这个神奇的数字是用utf-8还是utf-16或任何其他编码编码并不重要。这个数字仍然是一样的。
答案 3 :(得分:4)
正如其他答案中所指出的,fromCharCode()
和toCharCode()
处理基本多语言平面(BMP)中任何代码点的Unicode代码点。 JavaScript中的字符串是UCS-2编码的,BMP外部的任何代码点都表示为两个JavaScript字符。这些都不会改变。
要处理JavaScript端的任何Unicode字符,您可以使用以下函数,该函数将返回表示指定字符串的Unicode代码点序列的数字数组:
var getStringCodePoints = (function() {
function surrogatePairToCodePoint(charCode1, charCode2) {
return ((charCode1 & 0x3FF) << 10) + (charCode2 & 0x3FF) + 0x10000;
}
// Read string in character by character and create an array of code points
return function(str) {
var codePoints = [], i = 0, charCode;
while (i < str.length) {
charCode = str.charCodeAt(i);
if ((charCode & 0xF800) == 0xD800) {
codePoints.push(surrogatePairToCodePoint(charCode, str.charCodeAt(++i)));
} else {
codePoints.push(charCode);
}
++i;
}
return codePoints;
}
})();
var str = "";
var codePoints = getStringCodePoints(s);
console.log(str.length); // 2
console.log(codePoints.length); // 1
console.log(codePoints[0].toString(16)); // 1d306
答案 4 :(得分:3)
JavaScript字符串是UTF-16,这不是要改变的东西。
但不要忘记UTF-16是可变长度编码。
答案 5 :(得分:0)
在2018年,您可以使用String.codePointAt()和String.fromCodePoint()。
即使角色不在基本多语言平面(BMP)中,这些方法也能正常工作。