J'ai encodé NSData
UTF-8 à partir du serveur Windows et je souhaite le convertir en NSString
pour iPhone. Comme les données contiennent des caractères (comme un symbole de degré) qui ont des valeurs différentes sur les deux plates-formes, comment convertir des données en chaîne?
Si les données ne sont pas terminées par null, vous devez utiliser -initWithData:encoding:
NSString* newStr = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
Si les données sont terminées par null, vous devriez plutôt utiliser -stringWithUTF8String:
pour éviter le \0
supplémentaire à la fin.
NSString* newStr = [NSString stringWithUTF8String:[theData bytes]];
(Notez que si l'entrée n'est pas correctement encodée en UTF-8, vous obtiendrez nil
.)
let newStr = String(data: data, encoding: .utf8)
// note that `newStr` is a `String?`, not a `String`.
Si les données sont terminées par null, vous pouvez utiliser la méthode sécurisée qui consiste à supprimer le caractère NULL ou la méthode non sécurisée similaire à la version Objective-C ci-dessus.
// 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:))
Vous pouvez appeler cette méthode
+(id)stringWithUTF8String:(const char *)bytes.
Je soumets humblement une catégorie pour rendre cela moins ennuyeux:
@interface NSData (EasyUTF8)
// Safely decode the bytes into a UTF8 string
- (NSString *)asUTF8String;
@end
et
@implementation NSData (EasyUTF8)
- (NSString *)asUTF8String {
return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
}
@end
(Notez que si vous n'utilisez pas ARC, vous aurez besoin d'une autorelease
.)
Maintenant, au lieu de l'incroyable verbose:
NSData *data = ...
[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Tu peux faire:
NSData *data = ...
[data asUTF8String];
La version Swift de String to Data et retour à String:
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)
}
}
Cour de récréation
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"
Parfois, les méthodes des autres réponses ne fonctionnent pas. Dans mon cas, je génère une signature avec ma clé privée RSA et le résultat est NSData. J'ai trouvé que cela semble fonctionner:
Objectif c
NSData *signature;
NSString *signatureString = [signature base64EncodedStringWithOptions:0];
Rapide
let signatureString = signature.base64EncodedStringWithOptions(nil)
Pour résumer, voici une réponse complète, qui a fonctionné pour moi.
Mon problème était que quand j'ai utilisé
[NSString stringWithUTF8String:(char *)data.bytes];
La chaîne que j'avais était imprévisible: elle contenait environ 70% de la valeur attendue, mais trop souvent, elle entraînait Null
ou même pire: garbaged à la fin de la chaîne.
Après avoir creusé, je suis passé à
[[NSString alloc] initWithBytes:(char *)data.bytes length:data.length encoding:NSUTF8StringEncoding];
Et obtenu le résultat attendu à chaque fois.
Avec Swift 4.2, vous pouvez utiliser l'initialiseur init(data:encoding:)
de String
pour convertir une instance Data
en une instance String
en utilisant UTF-8. init(data:encoding:)
a la déclaration suivante:
init?(data: Data, encoding: String.Encoding)
Retourne une
String
initialisée en convertissant des données données en caractères Unicode en utilisant un codage donné.
Le code de Playground suivant montre comment l'utiliser:
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}")
*/