在使用initWithData等方法將NSData轉(zhuǎn)換成NSString時(shí),如果NSData的內(nèi)容含有非encoding編碼的字符,將會(huì)返回nil。
----------SDK文檔如下-------------
- (instancetype)initWithData:(NSData *)data
encoding:(NSStringEncoding)encoding;
Return Value
An NSString
object initialized by converting the bytes in data
into Unicode characters using encoding
. The returned object may be different from the original receiver. Returns nil
if the initialization fails for some reason (for example if data
does not represent valid data for encoding
).
這個(gè)結(jié)果在很多時(shí)候可能并不是我們所希望的,比如在獲取網(wǎng)頁(yè)源碼進(jìn)行分析等方面,如果頁(yè)面采用了utf-8編碼,只是含有個(gè)別非utf-8字符,我們更希望轉(zhuǎn)換NSString成功,拋棄(或替換)那些非法字符。
按照utf8格式標(biāo)準(zhǔn)
Unicode/UCS-4 | bit數(shù) | UTF-8 | byte數(shù) | 范圍(16進(jìn)制) |
0000 ~ 007F | 0~7 | 0XXX XXXX | 1 | 0x - 7x |
0080 ~ 07FF | 8~11 | 110X XXXX 10XX XXXX | 2 | Cx 8x - Dx Bx |
0800 ~ FFFF | 12~16 | 1110XXXX 10XX XXXX 10XX XXXX | 3 | Ex 8x 8x - Ex Bx Bx |
1 0000 ~ 1F FFFF | 17~21 | 1111 0XXX 10XX XXXX 10XX XXXX 10XX XXXX | 4 | F8 8x 8x 8x 8x - FB Bx Bx Bx Bx |
20 0000 ~ 3FF FFFF | 22~26 | 1111 10XX 10XX XXXX 10XX XXXX 10XX XXXX 10XX XXXX | 5 | FC 8x 8x 8x 8x 8x - FD Bx Bx Bx Bx Bx |
400 0000 ~ 7FFF FFFF | 27~31 | 1111 110X 10XX XXXX 10XX XXXX 10XX XXXX 10XX XXXX 10XX XXXX | 6 |
如果大于C0小于E0,表示2個(gè)字節(jié)組成的utf8字符(第一個(gè)是110開(kāi)頭的,第二個(gè)是10開(kāi)頭的);
如果大于E0小于F0,表示3個(gè)字節(jié)組成的utf8字符(第一個(gè)是1110開(kāi)頭的,第二個(gè)是10開(kāi)頭的,第三個(gè)是10開(kāi)頭的);
以此類(lèi)推,如果不符合utf-8規(guī)則,則表示一個(gè)非法字符,只要替換這樣的字符即可。
實(shí)現(xiàn)方法如下(此實(shí)現(xiàn)可用但不夠嚴(yán)謹(jǐn),如用于工程中建議進(jìn)行優(yōu)化):
//替換非utf8字符//注意:如果是三字節(jié)utf-8,第二字節(jié)錯(cuò)誤,則先替換第一字節(jié)內(nèi)容(認(rèn)為此字節(jié)誤碼為三字節(jié)utf8的頭),然后判斷剩下的兩個(gè)字節(jié)是否非法;- (NSData *)replaceNoUtf8:(NSData *)data{ char aa[] = {'A','A','A','A','A','A'}; //utf8最多6個(gè)字符,當(dāng)前方法未使用 NSMutableData *md = [NSMutableData dataWithData:data]; int loc = 0; while(loc < [md length]) { char buffer; [md getBytes:&buffer range:NSMakeRange(loc, 1)]; if((buffer & 0x80) == 0) { loc++; continue; } else if((buffer & 0xE0) == 0xC0) { loc++; [md getBytes:&buffer range:NSMakeRange(loc, 1)]; if((buffer & 0xC0) == 0x80) { loc++; continue; } loc--; //非法字符,將這個(gè)字符(一個(gè)byte)替換為A [md replaceBytesInRange:NSMakeRange(loc, 1) withBytes:aa length:1]; loc++; continue; } else if((buffer & 0xF0) == 0xE0) { loc++; [md getBytes:&buffer range:NSMakeRange(loc, 1)]; if((buffer & 0xC0) == 0x80) { loc++; [md getBytes:&buffer range:NSMakeRange(loc, 1)]; if((buffer & 0xC0) == 0x80) { loc++; continue; } loc--; } loc--; //非法字符,將這個(gè)字符(一個(gè)byte)替換為A [md replaceBytesInRange:NSMakeRange(loc, 1) withBytes:aa length:1]; loc++; continue; } else { //非法字符,將這個(gè)字符(一個(gè)byte)替換為A [md replaceBytesInRange:NSMakeRange(loc, 1) withBytes:aa length:1]; loc++; continue; } } return md;}
轉(zhuǎn)換后的NSData就可以正確轉(zhuǎn)換為NSString了。
*如果是非utf-8編碼,請(qǐng)自行對(duì)對(duì)應(yīng)照編碼協(xié)議轉(zhuǎn)換。
聯(lián)系客服