Tôi đã mã hóa UTF-8 NSData
từ máy chủ windows và tôi muốn chuyển đổi nó sang NSString
iPhone. Vì dữ liệu chứa các ký tự (như ký hiệu độ) có các giá trị khác nhau trên cả hai nền tảng, làm cách nào để chuyển đổi dữ liệu thành chuỗi?
Tôi đã mã hóa UTF-8 NSData
từ máy chủ windows và tôi muốn chuyển đổi nó sang NSString
iPhone. Vì dữ liệu chứa các ký tự (như ký hiệu độ) có các giá trị khác nhau trên cả hai nền tảng, làm cách nào để chuyển đổi dữ liệu thành chuỗi?
Câu trả lời:
Nếu dữ liệu không được kết thúc bằng null, bạn nên sử dụng -initWithData:encoding:
NSString* newStr = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
Nếu dữ liệu bị chấm dứt null, thay vào đó bạn nên sử dụng -stringWithUTF8String:
để tránh phần bổ sung \0
ở cuối.
NSString* newStr = [NSString stringWithUTF8String:[theData bytes]];
(Lưu ý rằng nếu đầu vào không được mã hóa UTF-8 đúng cách, bạn sẽ nhận được nil
.)
let newStr = String(data: data, encoding: .utf8)
// note that `newStr` is a `String?`, not a `String`.
Nếu dữ liệu bị chấm dứt null, bạn có thể đi theo cách an toàn là loại bỏ ký tự null đó hoặc cách không an toàn tương tự như phiên bản Objective-C ở trên.
// 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:))
Bạn có thể gọi phương thức này
+(id)stringWithUTF8String:(const char *)bytes.
NSData
biết nó có bao nhiêu byte ...
NSData
thành một NSString
(xem câu trả lời của KennyTM), tôi ngạc nhiên rằng không có +(id)stringWithUTF8Data:(NSData *)data
cái nào chỉ hoạt động.
Tôi khiêm tốn gửi một danh mục để làm cho điều này bớt khó chịu:
@interface NSData (EasyUTF8)
// Safely decode the bytes into a UTF8 string
- (NSString *)asUTF8String;
@end
và
@implementation NSData (EasyUTF8)
- (NSString *)asUTF8String {
return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
}
@end
(Lưu ý rằng nếu bạn không sử dụng ARC, bạn sẽ cần autorelease
đến đó.)
Bây giờ thay vì dài dòng kinh khủng:
NSData *data = ...
[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Bạn có thể làm:
NSData *data = ...
[data asUTF8String];
Phiên bản Swift từ Chuỗi sang Dữ liệu và quay lại Chuỗi:
Xcode 10.1 • Swift 4.2.1
extension Data {
var string: String? {
return String(data: self, encoding: .utf8)
}
}
extension StringProtocol {
var data: Data {
return Data(utf8)
}
}
extension String {
var base64Decoded: Data? {
return Data(base64Encoded: self)
}
}
Sân chơi
let string = "Hello World" // "Hello World"
let stringData = string.data // 11 bytes
let base64EncodedString = stringData.base64EncodedString() // "SGVsbG8gV29ybGQ="
let stringFromData = stringData.string // "Hello World"
let base64String = "SGVsbG8gV29ybGQ="
if let data = base64String.base64Decoded {
print(data) // 11 bytes
print(data.base64EncodedString()) // "SGVsbG8gV29ybGQ="
print(data.string ?? "nil") // "Hello World"
}
let stringWithAccent = "Olá Mundo" // "Olá Mundo"
print(stringWithAccent.count) // "9"
let stringWithAccentData = stringWithAccent.data // "10 bytes" note: an extra byte for the acute accent
let stringWithAccentFromData = stringWithAccentData.string // "Olá Mundo\n"
Đôi khi, các phương pháp trong các câu trả lời khác không hoạt động. Trong trường hợp của tôi, tôi đang tạo chữ ký bằng khóa riêng RSA của mình và kết quả là NSData. Tôi thấy rằng điều này dường như làm việc:
Mục tiêu-C
NSData *signature;
NSString *signatureString = [signature base64EncodedStringWithOptions:0];
Nhanh
let signatureString = signature.base64EncodedStringWithOptions(nil)
[[NSData alloc] initWithBase64EncodedString:signatureString options:0]
; Swift : NSData(base64EncodedString: str options: nil)
Tóm lại, đây là một câu trả lời hoàn chỉnh, có tác dụng với tôi.
Vấn đề của tôi là khi tôi sử dụng
[NSString stringWithUTF8String:(char *)data.bytes];
Chuỗi tôi nhận được là không thể đoán trước: Khoảng 70% nó chứa giá trị mong đợi, nhưng quá thường xuyên, nó dẫn đến Null
hoặc thậm chí tệ hơn: bị cắt xén ở cuối chuỗi.
Sau khi đào xong tôi chuyển sang
[[NSString alloc] initWithBytes:(char *)data.bytes length:data.length encoding:NSUTF8StringEncoding];
Và nhận được kết quả mong đợi mọi lúc.
Với Swift 5, bạn có thể sử dụng String
's init(data:encoding:)
initializer để chuyển đổi một Data
ví dụ thành một String
ví dụ sử dụng UTF-8. init(data:encoding:)
có tuyên bố sau:
init?(data: Data, encoding: String.Encoding)
Trả về một
String
khởi tạo bằng cách chuyển đổi dữ liệu đã cho thành các ký tự Unicode bằng cách sử dụng mã hóa đã cho.
Mã Playground sau đây cho biết cách sử dụng nó:
import Foundation
let json = """
{
"firstName" : "John",
"lastName" : "Doe"
}
"""
let data = json.data(using: String.Encoding.utf8)!
let optionalString = String(data: data, encoding: String.Encoding.utf8)
print(String(describing: optionalString))
/*
prints:
Optional("{\n\"firstName\" : \"John\",\n\"lastName\" : \"Doe\"\n}")
*/