解决NSData转NSString返回nil的问题

原创 2014年11月09日 02:17:38

在使用initWithData等方法将NSData转换成NSString时,如果NSData的内容含有非encoding编码的字符,将会返回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).

-----------------------------


这个结果在很多时候可能并不是我们所希望的,比如在获取网页源码进行分析等方面,如果页面采用了utf-8编码,只是含有个别非utf-8字符,我们更希望转换NSString成功,抛弃(或替换)那些非法字符。


按照utf8格式标准

Unicode/UCS-4
bit数
UTF-8
byte数
范围(16进制)
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


如果一个字节小于0x80,那么他就是一个字符;

如果大于C0小于E0,表示2个字节组成的utf8字符(第一个是110开头的,第二个是10开头的);

如果大于E0小于F0,表示3个字节组成的utf8字符(第一个是1110开头的,第二个是10开头的,第三个是10开头的);

以此类推,如果不符合utf-8规则,则表示一个非法字符,只要替换这样的字符即可。 


实现方法如下(此实现可用但不够严谨,如用于工程中建议进行优化):

//替换非utf8字符
//注意:如果是三字节utf-8,第二字节错误,则先替换第一字节内容(认为此字节误码为三字节utf8的头),然后判断剩下的两个字节是否非法;
- (NSData *)replaceNoUtf8:(NSData *)data
{
    char aa[] = {'A','A','A','A','A','A'};                      //utf8最多6个字符,当前方法未使用
    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--;
            //非法字符,将这个字符(一个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--;
            //非法字符,将这个字符(一个byte)替换为A
            [md replaceBytesInRange:NSMakeRange(loc, 1) withBytes:aa length:1];
            loc++;
            continue;
        }
        else
        {
            //非法字符,将这个字符(一个byte)替换为A
            [md replaceBytesInRange:NSMakeRange(loc, 1) withBytes:aa length:1];
            loc++;
            continue;
        }
    }
    
    return md;
}


转换后的NSData就可以正确转换为NSString了。


*如果是非utf-8编码,请自行对对应照编码协议转换。


版权声明:本文为博主原创文章,未经博主允许不得转载。博主微信:lofocus

NSData转NSString时为空

原因可能有很多,但很大程度是是因为编码问题。 明明拿到了NSData,确定此Data为NSString,可就是转换不成功。  NSStringEncoding myEncoding = ...
  • args_
  • args_
  • 2016年03月14日 17:29
  • 2194

NSData 转 NSString 为空的解决方法

在iOS底层网络的开发中,会遇到NSData 转 NSString 为空的情况,原因很多,下面的解决方法是针对从服务器传过来的数据中含有非UTF-8字符(主要是UTF-8)的情况。 用lib...
  • tieshuxianrezhang
  • tieshuxianrezhang
  • 2016年06月02日 21:48
  • 2643

Objective-c NSData转NSString后为nil 的解决办法

Apple官方的文档: Return Value An NSString object initialized by converting the bytes in data i...
  • xocom
  • xocom
  • 2016年03月16日 15:34
  • 2802

-initWithData: encoding:返回nil的解决办法

方法:-initWithData: encoding: 返回nil
  • drift_Axe
  • drift_Axe
  • 2017年06月07日 14:21
  • 679

iOS NSString 和 NSData 的相互转换

//NSString -> NSData NSData *data = [@"520it.com" dataUsingEncoding:NSUTF8StringEncoding]; //NSData ...
  • github_26672553
  • github_26672553
  • 2015年10月20日 16:13
  • 22914

苹果开发 笔记(79)NSData

NSData是一序列字节,用到地方还是挺多。今天整理一下。NSURLConnection 请求回来返回的字节。可能是JSON,XML,也有可能是其他格式。一些应用场景 NSString *j...
  • hero82748274
  • hero82748274
  • 2015年09月20日 10:00
  • 898

解决NSData转NSString返回nil的问题

在使用initWithData等方法将NSData转换成NSString时,如果NSData的内容含有非encoding编码的字符,将会返回nil。 ----------SDK文档如下-----...
  • u013263917
  • u013263917
  • 2015年04月16日 18:05
  • 636

iOS: NSString的方法initWithData:encoding:

- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
  • u011275873
  • u011275873
  • 2013年09月12日 22:05
  • 1231

iOS 10 NSData 转化为NSString 失败

遇到的问题 为了适配iOS 10 ,我新建了一个测试项目。结果发现了一个问题。就是NSData 转化为NSString  失败,使用  NSJSONSerialization 解析也失败。结果都是 n...
  • qq_25527655
  • qq_25527655
  • 2016年09月20日 15:38
  • 1386

Swift 3.0:String初始化器Encoding不能为nil的解决

以后会写一系列Swift 3.0中的小变化的博文,内容短小,因为我遇到这种问题就马上写下来,并不会刻意积累一大堆再一起写出来.如果大家有Swift 3.0使用上的问题欢迎提问.这个问题发生在之前可以执...
  • mydo
  • mydo
  • 2016年11月13日 19:57
  • 1241
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:解决NSData转NSString返回nil的问题
举报原因:
原因补充:

(最多只允许输入30个字)