NSString的length是怎么計(jì)算的?
蘋果API文檔是這樣解釋NSString的length方法:返回一個UTF-16編碼單元(碼元)的個數(shù)聚磺。
UTF-16是Unicode字符編碼五層次模型的第三層:字符編碼表(Character Encoding Form,也稱為 "storage format")的一種實(shí)現(xiàn)方式炬丸。即把Unicode字符集的抽象碼位映射為16位長的整數(shù)(即碼元)的序列瘫寝,用于數(shù)據(jù)存儲或傳遞。Unicode字符的碼位稠炬,需要1個或者2個16位長的碼元來表示焕阿,因此這是一個變長表示。
UTF-16比起UTF-8首启,好處在于大部分字符都以固定長度的字節(jié) (2字節(jié)) 儲存捣鲸,但UTF-16卻無法兼容于ASCII編碼。
通過UTF-16的定義闽坡,我們知道英文字母和一般漢字在UTF-16中用兩個字節(jié)表示,即占一個碼元愁溜,而一般的Emoji表情用四個字節(jié)表示疾嗅,即占兩個碼元。所以英文字母和漢字在NSString中的length為1冕象,而一般的Emoji表情在NSString中l(wèi)ength為2代承。
一個復(fù)雜表情到底能有多長
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
通過分析渐扮,這個復(fù)雜表情其實(shí)是由四個小表情(兩男兩女)和三個連接符號組合出來的:
每個小表情在UTF-16中占四個字節(jié)论悴,即2個碼元
每個連接符號在UTF-16中占兩個字節(jié),即1個碼元墓律。
所以,在NSString中l(wèi)ength為 42 + 31 = 11 (UTF-16碼元個數(shù))
但是當(dāng)把NSString轉(zhuǎn)換成UTF-8格式的NSData時膀估,數(shù)據(jù)是這樣存儲的:
每個小表情在UTF-8中占四個字節(jié)
每個連接符號在UTF-8中占三個字節(jié)
所以轉(zhuǎn)成NSData后的存儲總長度為 44 + 33 = 25 (字節(jié)個數(shù))。
補(bǔ)充:這種組合出來的復(fù)雜表情是蘋果自己定義的耻讽,不屬于Unicode編碼范圍察纯,但每個小表情屬于Unicode編碼范圍,所以將此表情發(fā)給安卓端针肥,會被顯示成多個連續(xù)的小表情饼记。而連接符本身顯示出來不占寬度,所以跟沒有連接符效果一樣慰枕。
如何完整的刪掉一個復(fù)雜表情具则?
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的長度是怎么計(jì)算的
因?yàn)镾wift的String沒有l(wèi)ength方法,所以獲取字符串長度是用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碼個數(shù))
let len = str.count
/// utf16編碼的長度(間接說明OC的NSString編碼是utf16的編碼)
let len1 = str.utf16.count
/// utf8編碼的長度
let len2 = str.utf8.count
拓展資料: