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.