【问题标题】:Conversion of NSData to NSString fails due to some charecters由于某些字符,将 NSData 转换为 NSString 失败
【发布时间】:2013-10-11 08:20:39
【问题描述】:

我正在使用以下方法将NSData 转换为NSString 作为网址的响应。

NSString *result = [[NSString alloc] initWithData:_Data encoding:NSUTF8StringEncoding];

它工作得很好,我已经使用了很长时间,但是今天我在一个页面上加载数据(分页)时遇到了一个问题,我的结果给出了null 字符串。

于是我搜了SO,从这个链接NSData to NSString converstion problem!找到了一个方法

[NSString stringWithCString:[theData bytes] length:[theData length]];

这很好用。

我的查询,

  1. 该方法在 iOS 2.0 中已弃用。如果我使用它,我将来会遇到任何问题吗?
  2. 我认为这是导致方法失败的文本 这是什么,有什么方法可以使用 NSUTF8StringEncoding 对其进行编码?
  3. 我可以使用什么替代编码来对上图中的所有字符类型进行编码?

【问题讨论】:

    标签: iphone ios objective-c encoding nsstring


    【解决方案1】:

    为了获取服务器发送的内容的类型,您需要检查响应的Content-Type标头。

    内容类型的值指定一个“MIMI类型”,例如:

    Content-Type: text/plain

    Content-Type 的值可以额外指定字符编码,例如:

    Content-Type: text/plain; charset=utf-8

    每个 MIME 类型应该定义一个“默认”字符集,在没有指定字符集参数时使用。

    对于text/* 媒体类型,默认字符集是US-ASCII。 (见RFC 6657, §3)。

    以下代码 sn-p 演示了如何安全地对响应的正文进行编码:

        - (NSString*) bodyString {
            CFStringEncoding cfEncoding = NSASCIIStringEncoding;
            NSString* textEncodingName = self.response.textEncodingName;
            if (textEncodingName) {
                cfEncoding = CFStringConvertIANACharSetNameToEncoding( (__bridge CFStringRef)(textEncodingName) );
            }
            if (cfEncoding != kCFStringEncodingInvalidId) {
                NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
                return [[NSString alloc] initWithData:self.body encoding:encoding];
            }        
            else {
                return [self.body description];
            }
        }
    

    注意:

    body 是一个属性,返回一个代表响应数据的NSData 对象。

    response 是一个返回 NSHTTPURLResponse 对象的属性。

    【讨论】:

    • 这是一个很好的通用解决方案,我还不知道CFStringConvertIANACharSetNameToEncoding()!
    • 一个更好的解决方案是考虑以前的,现在已经过时的,文本*媒体类型的默认编码:ISO-8859-1。也就是说,当没有指定字符集并且 US-ASCII 失败时,可以尝试 ISO-8859-1,然后再退回到原始二进制文件。
    • 为什么不首先尝试 ISO-8859-1(又名 NSISOLatin1StringEncoding)(如果没有指定字符集)?据我了解,这是 US-ASCII 的扩展,任意字节流的转换永远不会失败,因为所有字节 0x00 .. 0xFF 都映射到 U+00 .. U+FF 中的相应字符。跨度>
    • 是的,这是一个有效的选项 - 与任何其他 US-ASCII 兼容编码 (UTF-8) 一样。做不做,只看后面可能只懂US-ASCII的“字符串处理器”。如果您只想将其显示或记录到控制台,您当然可以使用 ISO-8858-1 或 UTF-8 对其进行编码(或者,使用“有损 ASCII 转换”)。否则,如果你想检查数据是否确实是US-ASCII,如果不是,你可以返回nil。最后,如果您需要不改变字节流(比如解析器),只需使用 NSData 对象,不要使用 NSString。
    • 谢谢@CouchDeveloper,我肯定会尝试这个解决方案。现在我对服务器用户进行了 utf-8 编码。为您的回答 +1
    【解决方案2】:

    如果

    NSString *result = [[NSString alloc] initWithData:_Data encoding:NSUTF8StringEncoding];
    

    返回 nil 然后 _Data 不包含 UTF-8 编码的有效字符串。

    你说过

    [NSString stringWithCString:[theData bytes] length:[theData length]];
    

    在您的情况下工作正常。这种方法 解释“默认 C 字符串编码”中的数据字节,但未指定哪个 编码是(因此该方法已被弃用,不应该使用 )。

    认为默认的 C 字符串编码仍然是“Mac Roman”。那样的话

    NSString *result = [[NSString alloc] initWithData:_Data encoding:NSMacOSRomanStringEncoding];
    

    将是正确的解决方案。但无论如何,你应该找出哪种编码 Web 服务用于响应,并在 initWithData:encoding: 中指定 方法。

    【讨论】:

    • 服务器没有使用任何编码。我现在才发现。让服务器使用utf8编码会解决问题吗
    • @vamsi575kg:是的,如果你有这个选项,让服务器使用 UTF-8 很有意义。
    • @vamsi575kg 在任何情况下,服务器都应该设置一个正确的Content-Type 标头。 content-type 标头指定内容的种类(例如图像、文本等)和其他属性,当内容为文本时可能是“字符集”。
    • @MartinR NSMacOSRomanStringEncoding 很可能是不正确的,因为发送数据的服务器不知道接收器的当前平台字符串实现的默认编码是什么;)
    • @CouchDeveloper:这只是一个猜测,基于 OP 的声明,它与 stringWithCString 配合得很好。我刚刚测试了它:该方法实际上使用了良好的旧 Mac Roman 编码。
    【解决方案3】:

    试试这个

    NSString *theString = [NSString stringWithFormat:@"To be continued%C", ellipsis];
    
    NSData *asciiData = [theString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    
    NSString *asciiString = [[NSString alloc] initWithData:asciiData encoding:NSASCIIStringEncoding];
    
    NSLog(@"Original: %@ (length %d)", theString, [theString length]);
    NSLog(@"Converted: %@ (length %d)", asciiString, [asciiString length]);
    

    【讨论】:

    • 这会将其转换为 ASCII,而不是 UTF8
    【解决方案4】:

    这是由于不正确的字符串编码。 你可以试试:

    1. 使用dataPathNSData 保存到磁盘
    2. 使用NSString类方法创建字符串:
    + (id)stringWithContentsOfURL:(NSURL *)url usedEncoding:(NSStringEncoding *)enc error:(NSError **)error
    

    请注意:

    编码

    返回时,如果 url 读取成功,则包含用于解释数据的编码。

    所以如果方法成功,你可以得到正确的字符串,一切都由iOS完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多