解決NSData中包含非法UTF-8編碼
我們開發中常會遇上將NSData轉換為NSString,或通過NSJSONSerialization解析JSON的場景,一旦NSData中包含非法的UTF-8編碼,那麼結果將是返回nil,但這樣的結果並不符合我們預期,因為可能這其中僅僅只是一個編碼錯誤,我們更希望將錯誤編碼丟棄或替換為錯誤字元.
在Google上找了一圈,有人也實現了這樣的方法,但個人覺得寫得不夠嚴謹,容錯性也不太好,索性自己寫一個吧,嚴格按照RFC3629的標準.
UTF-8是一種變長的編碼,針對不同長度的位元組有固定的格式,在RFC3629規範中最多隻能四個位元組,且對範圍有區間有要求,更多相關介紹請跳轉維基百科UTF-8詞條(跳轉地址):
1位元組0xxxxxxx
2位元組110xxxxx10xxxxxx
3位元組1110xxxx10xxxxxx10xxxxxx
4位元組11110xxx10xxxxxx10xxxxxx10xxxxxx
按照這樣的規則寫了一個NSData的擴充套件方法,見程式碼:
@implementationNSData(UTF8)
- (NSData*)UTF8Data
{
//儲存結果
NSMutableData*resData = [[NSMutableDataalloc] initWithCapacity:self.length];
//無效編碼替代符號(常見 � □ ?)
NSData*replacement = [@"�"dataUsingEncoding:NSUTF8StringEncoding];
uint64_t index =0;
constuint8_t *bytes =self.bytes;
while(index
{
uint8_t len =0;
uint8_t header = bytes[index];
//單位元組
if((header&0x80) ==0)
{
len =1;
}
//2位元組(並且不能為C0,C1)
elseif((header&0xE0) ==0xC0)
{
if(header !=0xC0&& header !=0xC1)
{
len =2;
}
}
//3位元組
elseif((header&0xF0) ==0xE0)
{
len =3;
}
//4位元組(並且不能為F5,F6,F7)
elseif((header&0xF8) ==0xF0)
{
if(header !=0xF5&& header !=0xF6&& header !=0xF7)
{
len =4;
}
}
//無法識別
if(len ==0)
{
[resData appendData:replacement];
index++;
continue;
}
//檢測有效的資料長度(後面還有多少個10xxxxxx這樣的位元組)
uint8_t validLen =1;
while(validLen < len && index+validLen
{
if((bytes[index+validLen] &0xC0) !=0x80)
break;
validLen++;
}
//有效位元組等於編碼要求的位元組數表示合法,否則不合法
if(validLen == len)
{
[resData appendBytes:bytes+index length:len];
}else
{
[resData appendData:replacement];
}
//移動下標
index += validLen;
}
returnresData;
}
@end
在Github上的連結地址:https://github.com/tanhaogg/THCategory
相關文章
- Ant編譯utf-8非法字元:/65279 解決方法編譯字元
- docker 容器指定utf-8編碼,解決中文亂碼Docker
- PHP中的字串、編碼、UTF-8PHP字串
- Unicode中UTF-8與UTF-16編碼詳解Unicode
- 簡單有效:解決 Excel 開啟 UTF-8 編碼 CSV 檔案亂碼的 BUGExcel
- 解決VS2005開啟UTF-8編碼文件亂碼問題(ZZ)
- Linux下修改MySQL資料庫字元編碼為UTF-8解決中文亂碼LinuxMySql資料庫字元
- Idea編碼UTF-8中.properties 配置檔案中文亂碼Idea
- PHP中的Malformed UTF-8 characters錯誤解決PHPORM
- flex中接收非utf-8編碼的後臺資料Flex
- 帶你瞭解 Unicode和UTF-8編碼知識Unicode
- 字元編解碼的故事(ASCII,ANSI,Unicode,Utf-8區別)字元ASCIIUnicode
- JS 簡單實現UTF-8編碼,Base64編碼JS
- UTF-8編碼與GBK編碼之間的轉換
- PHP中文GBK編碼轉UTF-8PHP
- Windows CMD永久設定UTF-8編碼Windows
- 設定Tomcat的UTF-8編碼Tomcat
- 字元編碼:ASCII,Unicode和UTF-8字元ASCIIUnicode
- windows下解決python輸出utf-8中文WindowsPython
- 解決python連線mysql,UTF-8亂碼問題PythonMySql
- 字元編碼:Unicode & UTF-16 & UTF-8字元Unicode
- linux上mysql編碼 utf-8設定LinuxMySql
- Python程式碼中文註釋出錯解決,使用UTF-8Python
- python中的編碼&解碼Python
- Linux下批量把GDK編碼的文章轉化為UTF-8編碼的文章以及“iconv: 未知 xxx 處的非法輸入序列”錯誤處理Linux
- 檔案boot.ini非法怎麼回事 boot.ini非法的解決辦法boot
- 學習電腦編碼utf-8,ansi編碼的基礎知識等
- PHP中文字元gbk編碼與UTF-8編碼的轉換PHP字元
- Python的編碼註釋# -*- coding:utf-8 -*-Python
- 字元編碼筆記:ASCII,Unicode和UTF-8字元筆記ASCIIUnicode
- 字元編碼筆記:ASCII,Unicode 和 UTF-8字元筆記ASCIIUnicode
- NSData 所有APIAPI
- Spring MVC 中文編碼亂碼解決SpringMVC
- Android 中的編碼與解碼Android
- 轉貼 (談談Unicode編碼,簡要解釋UCS、UTF、BMP、BOM等名詞)&(UTF-8編碼規則)Unicode
- Could not decode a text frame as UTF-8 的解決
- Windows Phone 7 中將Gb2312編碼轉換成UTF-8Windows
- Unicode、GBK、UTF-8、ASCII的編碼簡介UnicodeASCII