Objective c 将部分UTF-8解码为NSString
在使用Objective c 将部分UTF-8解码为NSString,objective-c,ios,utf-8,nsstring,nsurlconnection,Objective C,Ios,Utf 8,Nsstring,Nsurlconnection,在使用NSURLConnection类通过网络获取UTF-8编码文件时,很有可能代理的连接:didReceiveData:消息将与截断UTF-8文件的NSData一起发送,因为UTF-8是一种多字节编码方案,一个字符可以在两个单独的NSData 换句话说,如果我将从connection:didReceiveData:获得的所有数据合并在一起,我将拥有一个有效的UTF-8文件,但每个单独的数据都无效UTF-8() 我不想将所有下载的文件都存储在内存中 我想要的是:给定NSData,将任何可以解码的
NSURLConnection
类通过网络获取UTF-8
编码文件时,很有可能代理的连接:didReceiveData:
消息将与截断UTF-8
文件的NSData
一起发送,因为UTF-8
是一种多字节编码方案,一个字符可以在两个单独的NSData
换句话说,如果我将从connection:didReceiveData:
获得的所有数据合并在一起,我将拥有一个有效的UTF-8
文件,但每个单独的数据都无效UTF-8
()
我不想将所有下载的文件都存储在内存中
我想要的是:给定NSData
,将任何可以解码的内容解码为NSString
。万一最后
告诉我,NSData
的几个字节是未关闭的代理项,因此我可以将它们保存到下一个NSData
中
一个显而易见的解决方案是反复尝试使用
initWithData:encoding:
进行解码,每次都会截断最后一个字节,直到成功。不幸的是,这可能是非常浪费的。 UTF-8是一个非常简单的解析编码,它被设计成便于检测不完整的序列,如果你从一个不完整的序列中间开始,找到它的开始。
从末尾向后搜索一个0xc0字节。如果是=0xf0,则需要三个以下字节完成。 如果要确保在UTF-8多字节序列的中间不停止,则需要查看字节数组的末尾并检查前2位。
//假设receivedData同时包含剩余数据和新数据
无符号字符*数据=[receivedData字节];
UInteger字节计数=[receivedData长度];
if(字节数0)&&(lastByte&0xc0==0x80)){
倒计时++;
字节计数--;
lastByte=数据[byteCount-1];
}
//此时,要么耗尽字节数,要么获得初始字符
//如果我们耗尽字节数,我们可能处于非法序列中,这是我们应该做的
//在receivedData中始终具有初始字符
如果(字节数我有一个类似的问题-部分解码utf8
以前
NSString * adsTopic = [components[2] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
adsInfo->adsTopic = malloc(sizeof(char) * adsTopic.length + 1);
strncpy(adsInfo->adsTopic, [adsTopic UTF8String], adsTopic.length + 1);
在[解决]之后
NSString *adsTopic = [components[2] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSUInteger byteCount = [adsTopic lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"number of Unicode characters in the string topic == %lu",(unsigned long)byteCount);
adsInfo->adsTopic = malloc(byteCount+1);
strncpy(adsInfo->adsTopic, [adsTopic UTF8String], byteCount + 1);
NSString *text=[NSString stringWithCString:adsInfo.adsTopic encoding:NSUTF8StringEncoding];
NSLog(@"=== %@", text);
谢谢你的回答!(同时我意识到这就是解决方案)-我相信代码本身有一些缺点。(1)我认为数据[byteCount]
是不允许的,(2)数据
不一定包含代理项的开头。我建议为后代进行修复。我修复了一个错误,oops。至于不包含代理项开头的可能性,除非数据有错误(并且有检查),或者在调用此函数之前,您应该将以前的数据放在receivedData的开头(开头有注释)。因此,数据不应该包含序列的结尾而不是开头。同意,我的错误。再次感谢!
NSString *adsTopic = [components[2] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSUInteger byteCount = [adsTopic lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"number of Unicode characters in the string topic == %lu",(unsigned long)byteCount);
adsInfo->adsTopic = malloc(byteCount+1);
strncpy(adsInfo->adsTopic, [adsTopic UTF8String], byteCount + 1);
NSString *text=[NSString stringWithCString:adsInfo.adsTopic encoding:NSUTF8StringEncoding];
NSLog(@"=== %@", text);