解决NSData转NSString返回nil的问题

在使用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编码,请自行对对应照编码协议转换。

时间: 2024-08-05 16:52:16

解决NSData转NSString返回nil的问题的相关文章

iOS解决NSData转NSString后字符为空

iOS中,将NSData转NSString的一般方法为[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];但是当data中包含00时,所获得的新字符就会为nil,这时我们应该这样转 [NSString stringWithUTF8String:[data bytes]];

解决 pathForResource 返回 nil的问题

点击(此处)折叠或打开 NSString* path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"xml"]; NSLog(@"path=%@",path); NSError *error=nil; NSString* fileText = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncod

解决NSData中包含非法UTF-8编码

我们开发中常会遇上将NSData转换为NSString,或通过NSJSONSerialization解析JSON的场景,一旦NSData中包含非法的UTF-8编码,那么结果将是返回nil,但这样的结果并不符合我们预期,因为可能这其中仅仅只是一个编码错误,我们更希望将错误编码丢弃或替换为错误字符.在Google上找了一圈,有人也实现了这样的方法,但个人觉得写得不够严谨,容错性也不太好,索性自己写一个吧,严格按照RFC3629的标准. UTF-8是一种变长的编码,针对不同长度的字节有固定的格式,在R

NSData、NSString 、 NSFileManager

1 NSData和NSMutableData的基本使用 1.1 问题 NSData类是IOS提供的用于以二进制的形式操作文件数据的类,NSData有两个常用的属性length和bytes,length表示字节的数量,bytes起始字节的位置是一个指针类型,本案例演示NSData和NSMutableData的基本使用,使用NSData /NSMutableData对象保存一个C语言字符串. 1.2 方案 首先使用Xcode创建一个命令行项目,在main函数中创建一个NSData对象data,使用i

NSData NSDate NSString NSArray NSDictionary 相互转化

//    NSData  NSDate NSString NSArray NSDictionary json NSString *string = @"hello word"; NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3",nil

NSData与NSString

NSdata的概念 1.使用文件时需要频繁地将数据读入一个临时存储区,它通常称为缓冲区 2.NSdata类提供了一种简单的方式,它用来设置缓冲区,将文件的内容读入缓冲区,或者将缓冲区内容写到一个文件. 3.对于32位应用程序,NSdata缓存最多2GB 4.我们有两种定义 NSData(不可变缓冲区),NSMutableData(可变缓冲区) 上面的描述有点片面,再补充一些: NSData就是字节流的数据,它为字节流提供面向对象的存储空间,能够把一些字符串或图片等等一些非常复杂的数据类型转换成0

[NSURL URLWithString:] 返回nil

具体问题原因是url中输入的有中文,那么这个就看作非法的字符无法识别.这种的必须使用post方式来发送消息.具体为: tmp = mainurl;            [parameters appendString:key];            [parameters appendString:value]; NSURL * downloadUrl = [NSURL URLWithString:self.strURL];        NSMutableURLRequest *reque

NSData NSDate NSString NSArray NSDictionary 相互转换

// NSData NSDate NSString NSArray NSDictionary json NSString *string = @"hello word"; NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3",nil]; N

NSdata 与 NSString,Byte数组,UIImage 的相互转换

1. NSData 与 NSString NSData-> NSString NSString *aString = [[NSString alloc] initWithData:adataencoding:NSUTF8StringEncoding]; NSString->NSData NSString *aString = @"1234abcd"; NSData *aData = [aString dataUsingEncoding: NSUTF8StringEncodi