initWithData: encoding:NSUTF8StringEncoding return nil

  • 我们经常使用[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]将NSData数据以utf-8解码为字符串,但是如果NSData数据受损,则会返回nil,以下是苹果对该方法的解释。
    Returns nil if the initialization fails for some reason (for example if data does not represent valid data for encoding).

  • 解决办法是将受损的Byte找出来替换掉或者删掉。

  • 具体的查找原理可以参考这篇文章。十分钟搞清字符集和字符编码

  • 网上找的一段查找和替换代码。解决NSData转NSString返回nil的问题

  • 原帖代码有越界风险,我修改了一下并给代码做了注释。

//替换非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) //0xxx xxxx 1个Byte
        {
            loc++;
            continue;
        }
        else if ((buffer & 0xE0) == 0xC0) //110x xxxx 2个Byte
        {
            loc++; //此处可能越界,要判断
            if (loc >= md.length) { //此时的buffer已经是最后一个Byte
                loc--;
                //非法字符,将这个字符(一个byte)替换为A
                [md replaceBytesInRange:NSMakeRange(loc, 1) withBytes:aa length:1];
                break;
            }
            [md getBytes:&buffer range:NSMakeRange(loc, 1)];
            if ((buffer & 0xC0) == 0x80) //10xx xxxx 第2个Byte
            {
                loc++;
                continue;
            }
            loc--;
            //非法字符,将这个字符(一个byte)替换为A
            [md replaceBytesInRange:NSMakeRange(loc, 1) withBytes:aa length:1];
            loc++;
            continue;
        }
        else if ((buffer & 0xF0) == 0xE0) //1110 xxxx 3个Byte
        {
            loc++; //此处可能越界,要判断
            if (loc >= md.length) { //此时的buffer已经是最后一个Byte
                loc--;
                //非法字符,将这个字符(一个byte)替换为A
                [md replaceBytesInRange:NSMakeRange(loc, 1) withBytes:aa length:1];
                break;
            }
            [md getBytes:&buffer range:NSMakeRange(loc, 1)];
            if ((buffer & 0xC0) == 0x80) //10xx xxxx 第2个Byte
            {
                loc++; //此处可能越界,要判断
                if (loc >= md.length) { //此时的buffer已经是最后一个Byte
                    loc--;
                    //非法字符,将这个字符(一个byte)替换为A
                    [md replaceBytesInRange:NSMakeRange(loc, 1) withBytes:aa length:1];
                    break;
                }
                [md getBytes:&buffer range:NSMakeRange(loc, 1)];
                if ((buffer & 0xC0) == 0x80) //10xx xxxx 第3个Byte
                {
                    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;
}

你可能感兴趣的:(initWithData: encoding:NSUTF8StringEncoding return nil)