NSString的length是怎么计算的?
苹果API文档是这样解释NSString的length方法:返回一个UTF-16编码单元(码元)的个数。
UTF-16是Unicode字符编码五层次模型的第三层:字符编码表(Character Encoding Form,也称为 "storage format")的一种实现方式。即把Unicode字符集的抽象码位映射为16位长的整数(即码元)的序列,用于数据存储或传递。Unicode字符的码位,需要1个或者2个16位长的码元来表示,因此这是一个变长表示。
UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节 (2字节) 储存,但UTF-16却无法兼容于ASCII编码。
通过UTF-16的定义,我们知道英文字母和一般汉字在UTF-16中用两个字节表示,即占一个码元,而一般的Emoji表情用四个字节表示,即占两个码元。所以英文字母和汉字在NSString中的length为1,而一般的Emoji表情在NSString中length为2。
一个复杂表情到底能有多长
NSString* str = @"👩👩👦👦";
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"emoji str-len:%d data-len:%d",str.length,data.length);
输出:
emoji str-len:11 data-len:25
为何一个表情的长度能有11?
查看表情编码地址:https://apps.timwhitlock.info/unicode/inspect
通过分析,这个复杂表情其实是由四个小表情(两男两女)和三个连接符号组合出来的:
每个小表情在UTF-16中占四个字节,即2个码元
每个连接符号在UTF-16中占两个字节,即1个码元。
所以,在NSString中length为 42 + 31 = 11 (UTF-16码元个数)
但是当把NSString转换成UTF-8格式的NSData时,数据是这样存储的:
每个小表情在UTF-8中占四个字节
每个连接符号在UTF-8中占三个字节
所以转成NSData后的存储总长度为 44 + 33 = 25 (字节个数)。
补充:这种组合出来的复杂表情是苹果自己定义的,不属于Unicode编码范围,但每个小表情属于Unicode编码范围,所以将此表情发给安卓端,会被显示成多个连续的小表情。而连接符本身显示出来不占宽度,所以跟没有连接符效果一样。
如何完整的删掉一个复杂表情?
NSString* str = @"a问问👩👩👦👦";
NSRange range = [str rangeOfComposedCharacterSequenceAtIndex:str.length-1];
str = [str substringToIndex:range.location];
NSLog(@"emoji location:%d len:%d str:%@",range.location,range.length,str);
输出:
emoj location:3 len:11 str:a问问
String的长度是怎么计算的
因为Swift的String没有length方法,所以获取字符串长度是用count,然而OC的NSString用的则是.length获取长度,在有emoji的情况下,长度取的就不对
获取正确的length(等同于NSString的length)
/// "🐶"
let str = "\u{1F436}"
/// oc的NSString的字符串长度,也就是utf16编码的长度
let leng = (str as NSString).length
/// swift的String的count(unicode码个数)
let len = str.count
/// utf16编码的长度(间接说明OC的NSString编码是utf16的编码)
let len1 = str.utf16.count
/// utf8编码的长度
let len2 = str.utf8.count
拓展资料: