表情符号字符()与简单字符,lengthOfBytesUsingEncoding的结果不同

时间:2014-06-12 03:13:48

标签: string swift

我已经初始化了两个这样的字符常量:

let emojiCharacter = ""
let simpleCharacter = "a"

我正在打印lengthOfBytesUsingEncoding的结果:

println("\(emojiCharacter) countElements returns \(countElements(emojiCharacter))")
println("\(simpleCharacter) countElements returns \(countElements(simpleCharacter))")
println("\(emojiCharacter) UTF16StringEncoding lengthOfBytesUsingEncoding returns \(emojiCharacter.lengthOfBytesUsingEncoding(NSUTF16StringEncoding))")
println("\(simpleCharacter) UTF16StringEncoding lengthOfBytesUsingEncoding returns \(simpleCharacter.lengthOfBytesUsingEncoding(NSUTF16StringEncoding))")
println("\(emojiCharacter) NSUTF8StringEncoding lengthOfBytesUsingEncoding returns \(emojiCharacter.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))")
println("\(simpleCharacter) NSUTF8StringEncoding lengthOfBytesUsingEncoding returns \(simpleCharacter.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))")

以下是结果:

 countElements returns 1
a countElements returns 1
 UTF16StringEncoding lengthOfBytesUsingEncoding returns 4
a UTF16StringEncoding lengthOfBytesUsingEncoding returns 2
 NSUTF8StringEncoding lengthOfBytesUsingEncoding returns 4
a NSUTF8StringEncoding lengthOfBytesUsingEncoding returns 1

我对结果感到困惑,因为根据我的理解,如果我们使用UTF16StringEncoding然后它将每个字符视为2个字节或16位,如果我们使用UTF8StringEncoding,那么它将每个字符视为1个字节或8位,所以当我尝试使用UTF16StringEncoding记录simpleCharacter的lengthOfBytes,它显示2个字节,而对于NSUTF8StringEncoding,它显示1个字节。

我知道表情符号字符的表示方式不同,但为什么它总是将结果返回为4?

此外,如果我想迭代字符串中的每个字符,我将始终使用countElements,但是接下来究竟何时使用lengthOfBytesUsingEncoding会有帮助吗?

请建议。

2 个答案:

答案 0 :(得分:10)

UTF编码的大小只是定义用于表示字符的最小字节数。但是,某些字符(如您使用的表情符号)需要表示超过2个字节。所有字符至少取代编码中定义的最小值,最多可达到必要的字节数。

存在不同编码的各种原因,但为了给您一个快速示例:如果您知道要使用的所有字符都是2个字节或更少,则可以使用UTF-16编码的字符串以便您可以立即跳转到正常数组之类的任何索引处的字符,因为它们统一存储在内存中。如果你把它编码为UTF-8,你将无法再安全地跳入数组,因为有些字符用1个字节表示,而其他字符用超过1个字节表示,使得特定索引的位置在内存中不清楚。

答案 1 :(得分:1)

表情符号总是比您指定的类型(UTF16和UTF8)长,因为这两种尺寸都已满,因此无法存储表情符号包所需的其他符号。

正如您已经想到的那样,基本的拉丁字母可以放入一个字节:http://www.unicode.org/charts/PDF/U0000.pdf(注意,当读取表格时,U + XXXX值是一个16位十六进制代码,所以U + 0061 =(二进制)0000 0000 0110 0001,小写a)

当您添加更多语言和符号时,您需要使用两个字节:http://www.unicode.org/charts/PDF/U0080.pdf(U + 00E4 = 1100 0011 1010 0100 =ä)

但是,我需要在这里强调一点,因为我对此感到困惑。正如Drewag在他的回答和John Estropia在我的回答中所解释的那样,Unicode的字节大小仅描述了该编码中字符的最小大小。如您所见,您可以使用UTF8编码获得更大的表情符号字符,只需占用更多空间。

没有3字节的最小编码,因为它对当今使用的最常见的CPU没有意义。最新的Unicode标准是32位(4字节),是Emoji开始适应的地方:http://www.unicode.org/charts/PDF/Unicode-6.1/U61-1F600.pdf。请注意,U +之后现在有五个十六进制值,而不是之前看到的四个十六进制值,这需要至少3个字节的寻址。

因此,如果您使用UTF32,您会看到基本拉丁字符在表情符号处出现的大小相同。

作为您希望以编程方式查找lengthOfBytesUsingEncoding的示例,假设您正在编写一个程序,通过某种算法*压缩文本文件。要进行编码或解码,您需要知道原始文件中字符的长度。你以某种方式给出了编码,对于不同的文本文件可能会有所不同。你可能有一堆if / else块,包含所有可能的编码(在你编写程序时),或者你可以有一个很好的变量,它从lengthOfBytesUsingEncoding获取它的值(这里插入编码)。
*我在考虑霍夫曼压缩,但可能还有其他例子......

我希望我能想到一个更好的 - 每天 - 例子!但是,一般来说,我会说你不需要知道给定编码中字符的字节长度。