web-dev-qa-db-fra.com

Convertir NSData encodé en UTF-8 en NSString

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?

553
Ashwini

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.)


Variante rapide:

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:))
1132
kennytm

Vous pouvez appeler cette méthode 

+(id)stringWithUTF8String:(const char *)bytes.
28
Gouldsc

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];
19
Claudiu

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"
18
Leo Dabus

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)
15
mikeho

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.

1
Gal

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}")
*/
0
Imanou Petit