ios nsstring nsdata

ios - Convertir UTD-8 codificados NSData a NSString



(6)

A veces, los métodos en las otras respuestas no funcionan. En mi caso, estoy generando una firma con mi clave privada RSA y el resultado es NSData. Encontré que esto parece funcionar:

C objetivo

NSData *signature; NSString *signatureString = [signature base64EncodedStringWithOptions:0];

Rápido

let signatureString = signature.base64EncodedStringWithOptions(nil)

Tengo NSData codificado en UTF-8 del servidor de Windows y quiero convertirlo a NSString para iPhone. Dado que los datos contienen caracteres (como un símbolo de grado) que tienen valores diferentes en ambas plataformas, ¿cómo convierto los datos en una cadena?


Humildemente presento una categoría para hacer esto menos molesto:

@interface NSData (EasyUTF8) // Safely decode the bytes into a UTF8 string - (NSString *)asUTF8String; @end

y

@implementation NSData (EasyUTF8) - (NSString *)asUTF8String { return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding]; } @end

(Tenga en cuenta que si no está usando ARC, necesitará una autorelease allí).

Ahora en lugar de lo espantosamente detallado:

NSData *data = ... [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

Tu puedes hacer:

NSData *data = ... [data asUTF8String];


La versión Swift de String a Data y de vuelta a String:

Xcode 9 • Swift 4

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

Patio de recreo

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) // "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"


Podrías llamar a este método.

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


Si los datos no están terminados en nulo, debe usar -initWithData:encoding:

NSString* newStr = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];

Si los datos están terminados en nulo, en su lugar debería usar -stringWithUTF8String: para evitar el extra /0 al final.

NSString* newStr = [NSString stringWithUTF8String:[theData bytes]];

(Tenga en cuenta que si la entrada no está correctamente codificada en UTF-8, obtendrá nil ).

Variante Swift:

let newStr = String(data: data, encoding: .utf8) // note that `newStr` is a `String?`, not a `String`.

Si los datos están terminados en nulo, puede ir por la forma segura que es eliminar el carácter nulo, o la forma insegura similar a la versión de Objective-C anterior.

// 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:))


Solo para resumir, aquí hay una respuesta completa, que funcionó para mí.

Mi problema era que cuando lo usaba

[NSString stringWithUTF8String:(char *)data.bytes];

La cadena que obtuve fue impredecible: alrededor del 70% contenía el valor esperado, pero con demasiada frecuencia resultó con Null o incluso peor: se empaquetó al final de la cadena.

Después de algo de excavación cambié a

[[NSString alloc] initWithBytes:(char *)data.bytes length:data.length encoding:NSUTF8StringEncoding];

Y obtuve el resultado esperado cada vez.