【问题标题】:NSData to NSString converstion problem!NSData 到 NSString 的转换问题!
【发布时间】:2010-11-27 10:17:27
【问题描述】:

我得到一个作为 NSData 的 html 文件,需要对其进行解析以提取一些信息。我的方法是使用 UTF8 编码将其转换为 NSString(html 有非英文字符,例如俄语) - 它失败了。我用过类似的东西:

NSString *respData = [NSString stringWithUTF8String:[theData bytes]];

但它返回 nil。

唯一真正起作用的是

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

但是当它遇到例如俄语字符时,它会返回 jibrish。

然后我的下一个方法是解析数据的字节数组,提取我需要的字节并以某种方式将它们转换为 NSString。我尝试了类似的方法:

-(NSString *)UTF8StringFromData:(NSData *)theData{
 Byte *arr = [theData bytes];
 NSUInteger begin1 = [self findIndexOf:@"<li>" bArr:arr size:[theData length]]+4;
 NSUInteger end1 = [self findIndexOf:@"</li></ol>" bArr:arr size:[theData length]];
 Byte *arr1 = (Byte *)malloc(sizeof(Byte)*((end1-begin1+1)));
 int j = 0;
 for (int i = begin1; i < end1; i++){
  arr1[j] = arr[i];
  j++;
 }
 arr1[j]='\0';
 NSData *temp = [NSData dataWithBytes:arr1 length:j];
 return [[NSString alloc] initWithData:temp encoding:NSUTF8StringEncoding];
}

【问题讨论】:

  • 确定该文件被编码为 UTF-8,而不是 ISO 8859-5 之类的吗?

标签: iphone objective-c encoding nsstring nsdata


【解决方案1】:

假设你得到一个 NSURLResponse* 响应和一个 NSData* 数据:

CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef) [response textEncodingName]);
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);

NSString* string = [[NSString alloc] initWithData:data encoding:encoding];

// Do stuff here..

[string release];

【讨论】:

  • 我正在为我的项目使用启用了 ARC 的 xcode 4,当我使用上面的代码时,它抱怨 Cast of Objective-C pointer type 'NSString *' to C pointer type 'CFStringRef' (aka 'const struct __CFString *') requires a bridged cast。当我实施任何建议的修复程序(使用__bridge__bridge_retained)时,我会在程序运行时收到 EXC_BAD_ACCESS 信号。有什么想法吗?
  • 应该是(__bridge CFStringRef) [response textEncodingName]。这两个都不起作用向我表明问题出在其他地方。打开 NSZombieEnabled 并使用 CFZombieLevel 来追踪释放的内存访问。
  • 感谢您的回复。这听起来相当复杂,而且我完全是 iOS 开发的菜鸟,但我会检查一下。我最终通过使用可怕的代码解决了这个问题:char* myenc = malloc([responseEncoding length]); [[_response textEncodingName] getCString:myenc maxLength:[responseEncoding length] encoding:NSASCIIStringEncoding]; CFStringRef encenc = CFStringCreateWithCString(kCFAllocatorDefault, myenc, kCFStringEncodingASCII); CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding(encenc); free(myenc);
【解决方案2】:

我在这里回复上面的 Martijn Thé 线程,因为我无法在 cmets 中放入可读的代码 sn-p。

我发现如果在服务器上,响应内容类型设置为'text/plain',那么 (__bridge CFStringRef) [response textEncodingName] 将为空,如果你尝试将它传递给 CFStringConvertIANACharSetNameToEncoding 你会得到一个EXC_BAD_ACCESS 信号。

如果响应的内容类型设置为'text/html; charset=utf-8',然后一切都按预期工作。为了处理 'text/plain' 内容类型,这就是我所做的:

CFStringRef sRef = (__bridge CFStringRef)[response textEncodingName];
if (sRef)
{
        CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding(sRef);
        encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
}
else
{
        encoding = NSASCIIStringEncoding;
}

【讨论】:

    【解决方案3】:

    首先是我的代码

    -(NSString *)UTF8StringFromData:(NSData *)theData{
        Byte *arr = [theData bytes];
        NSUInteger begin1 = [self findIndexOf:@"<li>" bArr:arr size:[theData length]]+4;
        NSUInteger end1 = [self findIndexOf:@"</li></ol>" bArr:arr size:[theData length]];
        Byte *arr1 = (Byte *)malloc(sizeof(Byte)*((end1-begin1+1)));
        int j = 0;
        for (int i = begin1; i < end1; i++){
            arr1[j] = arr[i];
            j++;
        }
        arr1[j]='\0';
        NSData *temp = [NSData dataWithBytes:arr1 length:j];
        return [[NSString alloc] initWithData:temp encoding:NSUTF8StringEncoding];  
    }
    

    第二个 - 我从网络上获取文件内容 - 所以我不能确定任何事情。如果有帮助,它是谷歌翻译的 html...

    【讨论】:

    • 没人知道吗? ...来吧...之前一定有人遇到过这个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多