将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]; 

每次都得到预期的结果。