将UTF-8编码的NSData转换为NSString
我有来自Windows服务器的UTF-8编码的NSData
,我想将它转换为iPhone的NSString
。 由于数据包含两个平台上具有不同值的字符(如度符号),因此如何将数据转换为string?
如果数据不是空终止的,你应该使用-initWithData:encoding:
NSString* newStr = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
如果数据是以空字符结尾的,则应该使用-stringWithUTF8String:
来避免在结尾处多余的\0
。
NSString* newStr = [NSString stringWithUTF8String:[theData bytes]];
(请注意,如果input不正确的UTF-8编码,你会得到nil
。)
Swift变种:
let newStr = String(data: data, encoding: .utf8) // note that `newStr` is a `String?`, not a `String`.
如果数据是以空字符结尾的,那么可以通过删除空字符的安全方式,或者类似于上述Objective-C版本的不安全方式。
// safe way, provided data is \0-terminated let newStr1 = String(data: data.subdata(in: 0 ..< data.count - 1), encoding: .utf8) // unsafe way, provided data is \0-terminated let newStr2 = data.withUnsafeBytes(String.init(utf8String:))
你可以调用这个方法
+(id)stringWithUTF8String:(const char *)bytes.
我虚心地提交一个类别,使其不那么讨厌:
@interface NSData (EasyUTF8) // Safely decode the bytes into a UTF8 string - (NSString *)asUTF8String; @end
和
@implementation NSData (EasyUTF8) - (NSString *)asUTF8String { return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding]; } @end
(请注意,如果您不使用ARC,则需要在那里使用autorelease
。)
现在,而不是令人吃惊的详细:
NSData *data = ... [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
你可以做:
NSData *data = ... [data asUTF8String];
从string到数据并返回string的Swift版本:
Xcode 8.3.1•Swift 3.1
extension Data { var string: String { return String(data: self, encoding: .utf8) ?? "" } } extension String { var data: Data { return Data(utf8) } var base64Decoded: Data? { return Data(base64Encoded: self) } }
操场
let myString = "Hello World" // "Hello World" let myStringData = myString.data // 11 bytes let myDataBase64 = myStringData.base64EncodedString() // "SGVsbG8gV29ybGQ=" let myDataString = myStringData.string // "Hello World"
let myBase64String = "SGVsbG8gV29ybGQ=" if let myBase64Data = myBase64String.base64Decoded { print(myBase64Data) // 11 bytes print(myBase64Data.base64EncodedString()) // "SGVsbG8gV29ybGQ=" print(myBase64Data.string) // "Hello World" }
let stringWithAccent = "Olá Mundo" // "Olá Mundo" print(stringWithAccent.characters.count) // "9" let stringWithAccentData = stringWithAccent.data // "10 bytes" note: an extra byte for the acute accent let stringFromData = stringWithAccentData.string // "Olá Mundo\n"
有时,其他答案中的方法不起作用。 在我的情况下,我用我的RSA私钥生成一个签名,结果是NSData。 我发现这似乎工作:
Objective-C的
NSData *signature; NSString *signatureString = [signature base64EncodedStringWithOptions:0];
迅速
let signatureString = signature.base64EncodedStringWithOptions(nil)
总而言之,这是一个完整的答案,对我来说很有效。
我的问题是,当我使用
[NSString stringWithUTF8String:(char *)data.bytes];
我得到的string是不可预知的:大约70%的string包含期望的值,但是经常会导致Null
甚至更糟:在string末尾的垃圾邮件。
经过一些挖掘,我切换到
[[NSString alloc] initWithBytes:(char *)data.bytes length:data.length encoding:NSUTF8StringEncoding];
每次都得到预期的结果。