Esta es una categoría aplicada a NSData que escribí. Devuelve un NSString hexadecimal que representa el NSData, donde los datos pueden tener cualquier longitud. Devuelve una cadena vacía si NSData está vacío.
NSData + Conversion.h
#import <Foundation/Foundation.h>
@interface NSData (NSData_Conversion)
#pragma mark - String Conversion
- (NSString *)hexadecimalString;
@end
NSData + Conversion.m
#import "NSData+Conversion.h"
@implementation NSData (NSData_Conversion)
#pragma mark - String Conversion
- (NSString *)hexadecimalString {
/* Returns hexadecimal string of NSData. Empty string if data is empty. */
const unsigned char *dataBuffer = (const unsigned char *)[self bytes];
if (!dataBuffer)
return [NSString string];
NSUInteger dataLength = [self length];
NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (int i = 0; i < dataLength; ++i)
[hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];
return [NSString stringWithString:hexString];
}
@end
Uso:
NSData *someData = ...;
NSString *someDataHexadecimalString = [someData hexadecimalString];
Esto es "probablemente" mejor que llamar [someData description]
y luego quitar los espacios, <y>. Despojar a los personajes se siente demasiado "hacky". Además, nunca se sabe si Apple cambiará el formato de NSData -description
en el futuro.
NOTA: Algunas personas se comunicaron conmigo sobre la licencia del código en esta respuesta. Por la presente, dedico mis derechos de autor sobre el código que publiqué en esta respuesta al dominio público.
"%02lx"
con ese elenco, o lanzar a(unsigned int)
, o quitar el elenco y usar@"%02hhx"
:)[hexString appendFormat:@"%02x", (unsigned int)dataBuffer[i]];
es mucho mejor (menor huella de memoria)Aquí hay un método de categoría NSData altamente optimizado para generar una cadena hexadecimal. Si bien la respuesta de @Dave Gallagher es suficiente para un tamaño relativamente pequeño, el rendimiento de la memoria y la CPU se deteriora para grandes cantidades de datos. Hice un perfil de esto con un archivo de 2 MB en mi iPhone 5. La comparación de tiempo fue 0.05 vs 12 segundos. La huella de memoria es insignificante con este método, mientras que el otro método aumentó el volumen a 70 MB.
fuente
El uso de la propiedad de descripción de NSData no debe considerarse un mecanismo aceptable para la codificación HEX de la cadena. Esa propiedad es solo para descripción y puede cambiar en cualquier momento. Como nota, antes de iOS, la propiedad de descripción NSData ni siquiera devolvía sus datos en forma hexadecimal.
Lo siento por insistir en la solución, pero es importante tomarse la energía para serializarla sin tener que recurrir a una API que está destinada a algo más que a la serialización de datos.
fuente
description
devuelve una cadena codificada en hexadecimal, por lo que me parece razonable.A continuación, se muestra una forma más rápida de realizar la conversión:
BenchMark (tiempo medio para una conversión de datos de 1024 bytes repetida 100 veces):
Dave Gallagher: ~ 8.070 ms
NS Programador: ~ 0.077 ms
Peter: ~ 0.031 ms
Este: ~ 0.017 ms
fuente
_hexString
método): github.com/ZipArchive/ZipArchive/blob/master/SSZipArchive/…Versión funcional Swift
Un trazador de líneas:
Aquí está en un formulario de extensión reutilizable y autodocumentado:
Alternativamente, use en
reduce("", combine: +)
lugar dejoinWithSeparator("")
ser visto como un maestro funcional por sus compañeros.Editar: cambié String ($ 0, base: 16) a String (formato: "% 02x", $ 0), porque se necesitaban números de un dígito para tener un cero de relleno
fuente
La respuesta de Peter se transfirió a Swift.
swift3
Rápido 5
fuente
Necesitaba resolver este problema y las respuestas aquí me resultaron muy útiles, pero me preocupa el rendimiento. La mayoría de estas respuestas implican copiar los datos a granel de NSData, así que escribí lo siguiente para hacer la conversión con poca sobrecarga:
Esto preasigna espacio en la cadena para todo el resultado y evita copiar el contenido de NSData utilizando enumerateByteRangesUsingBlock. Cambiar la X por una x en la cadena de formato usará dígitos hexadecimales en minúscula. Si no desea un separador entre los bytes, puede reducir la declaración
hasta solo
fuente
NSRange
indica el rango dentro de laNSData
representación más grande , no dentro del búfer de bytes más pequeño (ese primer parámetro del bloque suministradoenumerateByteRangesUsingBlock
) que representa una sola porción contigua del más grandeNSData
. Por lo tanto,byteRange.length
refleja el tamaño del búfer de bytes, perobyteRange.location
es la ubicación dentro del mayorNSData
. Por lo tanto, desea usar simplementeoffset
, nobyteRange.location + offset
, para recuperar el byte.appendFormat
, probablemente también debería cambiarself.length * 3
aself.length * 2
Necesitaba una respuesta que funcionara para cadenas de longitud variable, así que esto es lo que hice:
Funciona muy bien como una extensión para la clase NSString.
fuente
Siempre puede usar [yourString uppercaseString] para poner letras en mayúscula en la descripción de los datos
fuente
Una mejor manera de serializar / deserializar NSData en NSString es usar el codificador / decodificador Google Toolbox para Mac Base64. Simplemente arrastre a su proyecto de aplicación los archivos GTMBase64.m, GTMBase64.he GTMDefines.h del paquete Foundation y haga algo como
fuente
string = [data base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]
Aquí hay una solución usando Swift 3
fuente
fuente
Cambie
%08x
a%08X
para obtener caracteres en mayúscula.fuente
Swift + Propiedad.
Prefiero tener una representación hexadecimal como propiedad (lo mismo que
bytes
ydescription
propiedades):La idea se toma prestada de esta respuesta
fuente
Deberá eliminar los espacios.
Personalmente
base64
codifico eldeviceToken
, pero es cuestión de gustos.fuente