Convierta NSData codificado en UTF-8 a NSString

Tengo NSData codificado en UTF-8 desde el servidor de Windows y quiero convertirlo a NSString para iPhone. Como 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?

Si los datos no tienen terminación nula, debe usar -initWithData:encoding:

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

Si los datos tienen terminación nula, en su lugar debe usar -stringWithUTF8String: para evitar el extra \0 al final.

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

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


Variante Swift:

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

Si los datos son terminados en nulo, puedes ir por la ruta segura que es eliminar el carácter nulo, o la forma insegura similar a la versión anterior de 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:)) 

Puedes llamar a este método

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

Humildemente presento una categoría para que esto sea 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 terriblemente detallado:

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

Tu puedes hacer:

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

La versión de 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" 

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. Descubrí que esto parece funcionar:

C objective

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

Rápido

 let signatureString = signature.base64EncodedStringWithOptions(nil) 

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

Mi problema era que cuando usaba

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

El hilo que recibí era impredecible: alrededor del 70% contenía el valor esperado, pero con demasiada frecuencia resultaba con Null o incluso peor: con el relleno al final de la cadena.

Después de cavar, cambié a

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

Y obtuve el resultado esperado todo el tiempo.