本文正在参与「金石计划 . 瓜分6万现金大奖」

原作者:Daniel Lemire

原文地址:lemire.me/blog/2018/0…

emoji 是有趣的字符,而且越来越流行。可是,关于程序员来说,处理 emoji 或许并不像你幻想的那样简略。为了对比,咱们经过 Python3 来运用 emoji。代码如下,咱们界说了一个包含表情符号的字符串,然后拜访索引 1 的字符(第二个字符)。

>>> x= ""
>> len(x)
4
>>> x[1]
''
>>> x[2]
''

能够看出,这样做的作用很好。可是,这在 Python2 中失利了。所以请升级到 Python3 (Python3十年前就出来了)。

那么JavaJavaScript的作用会怎么样呢?它们两个类似,这儿将专心于Java。在java 中,你能够很很简略地界说 emoji 的字符串。

String emostring = ""

可是,这只是费事的开始。假如你企图获取字符串的长度(emostring.length()),Java 会告知你这个字符串包含 8 个字符。假如要在 “unicode代码点” 中取得字符串的正确长度,你需求运用 emostring.codePointCount(0, emostring.length()),该办法会回来4。这不仅耗时较长,而且我估计该办法的计算成本也会高得多。

那么拜访字符呢?你或许认为 emostring.charAt(1) 会回来第二个字符(),可是它失利了。由于Java运用UTF-16编码,这意味着,一个unicode字符能够运用一个16位或两个16位来表明,这取决于字符的情况。因而,假如给你一串字符串的字节省,你不扫描它就无法知道这个字符串有多长。一起,Java中的字符类型(char)是16位的,所以它不能表明一切的 unicode字符。例如,你不能用Java的char来表明一个表情符号。在Java中,为了得到第二个字符,你需求做一些费事的操作,比方说:

new StringBuilder().appendCodePoint(
emostring.codePointAt(emostring.offsetByCodePoints(0, 1)).toString()

我相信你能够找到更短的办法,但这是它的关键。而且,它比 charAt 要耗时得多。

假如你的应用程序需求随机拜访一个长字符串中的 unicode字符,你就有或许呈现功能问题。
其他语言的完成,比方 PyPy(PyPy是用Python完成的Python解释器的动态编译器) 运用 UTF-32 编码,与 JavaUTF-16 编码不同,它支持对单个字符的快速随机拜访。缺点是内存占用增加。事实上,PyPy 好像想转向UTF-8,这是现在网络上的主流格局。在UTF-8中,字符用1、2、3或4个字节表明。

这儿面有不同的权衡。假如内存不是问题,而且你期望运用表情符号,而且能在长字符串中快速随机拜访,我认为UTF-32更有优势;假如你想要类似UTF-8这样的格局,来取得一些杰出的功能,一起对长字符串有某种方式的索引,假如你运用的语言不允许你直接拜访底层完成,这或许很难完成。

比功能更烦人的是对程序员的朴实的不方便。现在是2018年(文章发布时刻是2018年,译者注)。拜访一串表情符号中的第二个表情符号需求几乎无法解读的代码,这实在令人无法承受。

附录:是的。我知道不同的代码点能够组合成一个可见的字符,所以我把 “字符 “和 “代码点 “等同起来,为了简化问题。我也知道,不同的码点序列能够发生相同的字符。但这只会使现在的编程状况更糟。