2010-06-16 22 views
26

Me gustaría convertir un NSString normal en un NSString con los (lo que supongo que son) valores hexadecimales ASCII y viceversa.Cómo convertir un NSString en valores hexadecimales

Necesito producir el mismo resultado que los métodos de Java a continuación, pero parece que no puedo encontrar la manera de hacerlo en Objective-C. He encontrado algunos ejemplos en C y C++ pero me ha costado trabajo incorporarlos en mi código.

Éstos son los métodos de Java que estoy tratando de reproducir:

/** 
* Encodes the given string by using the hexadecimal representation of its UTF-8 bytes. 
* 
* @param s The string to encode. 
* @return The encoded string. 
*/ 
public static String utf8HexEncode(String s) { 
    if (s == null) { 
     return null; 
    } 
    byte[] utf8; 
    try { 
     utf8 = s.getBytes(ENCODING_UTF8); 
    } catch (UnsupportedEncodingException x) { 
     throw new RuntimeException(x); 
    } 
    return String.valueOf(Hex.encodeHex(utf8)); 
} 

/** 
* Decodes the given string by using the hexadecimal representation of its UTF-8 bytes. 
* 
* @param s The string to decode. 
* @return The decoded string. 
* @throws Exception If an error occurs. 
*/ 
public static String utf8HexDecode(String s) throws Exception { 
if (s == null) { 
    return null; 
} 
    return new String(Hex.decodeHex(s.toCharArray()), ENCODING_UTF8); 
} 

Actualización: Gracias a drawnonward de la respuesta del método que escribí para crear las NSStrings hexagonales aquí. Me da una advertencia de "inicialización descarta calificadores del tipo de destino del puntero" en la línea de declaración de char, pero funciona.

- (NSString *)stringToHex:(NSString *)string 
{ 
    char *utf8 = [string UTF8String]; 
    NSMutableString *hex = [NSMutableString string]; 
    while (*utf8) [hex appendFormat:@"%02X" , *utf8++ & 0x00FF]; 

    return [NSString stringWithFormat:@"%@", hex]; 
} 

No he tenido tiempo para escribir el método de descodificación. Cuando lo haga, editaré esto para publicarlo para cualquier otra persona interesada.

Update2: Por lo tanto, el método que publiqué anteriormente en realidad no muestra lo que estoy buscando. En lugar de dar salida a valores hexadecimales en formato 0-f, en cambio, daba salida a todos los números. Finalmente volví a trabajar en este problema y pude escribir una categoría para NSString que duplica exactamente los métodos de Java que publiqué. Aquí está:

// 
// NSString+hex.h 
// Created by Ben Baron on 10/20/10. 
// 

@interface NSString (hex) 

    + (NSString *) stringFromHex:(NSString *)str; 
    + (NSString *) stringToHex:(NSString *)str; 

@end 

// 
// NSString+hex.m 
// Created by Ben Baron on 10/20/10. 
// 

#import "NSString+hex.h" 

@implementation NSString (hex) 

+ (NSString *) stringFromHex:(NSString *)str 
{ 
    NSMutableData *stringData = [[[NSMutableData alloc] init] autorelease]; 
    unsigned char whole_byte; 
    char byte_chars[3] = {'\0','\0','\0'}; 
    int i; 
    for (i=0; i < [str length]/2; i++) { 
     byte_chars[0] = [str characterAtIndex:i*2]; 
     byte_chars[1] = [str characterAtIndex:i*2+1]; 
     whole_byte = strtol(byte_chars, NULL, 16); 
     [stringData appendBytes:&whole_byte length:1]; 
    } 

    return [[[NSString alloc] initWithData:stringData encoding:NSASCIIStringEncoding] autorelease]; 
} 

+ (NSString *) stringToHex:(NSString *)str 
{ 
    NSUInteger len = [str length]; 
    unichar *chars = malloc(len * sizeof(unichar)); 
    [str getCharacters:chars]; 

    NSMutableString *hexString = [[NSMutableString alloc] init]; 

    for(NSUInteger i = 0; i < len; i++) 
    { 
     [hexString appendString:[NSString stringWithFormat:@"%x", chars[i]]]; 
    } 
    free(chars); 

    return [hexString autorelease]; 
} 

@end 
+0

tengo este código en su casa. Lo publicaré cuando salga del trabajo a menos que alguien me golpee. –

+0

Hola, sé que esta es una publicación anterior. Pero me encontré con tu problema al que me enfrenté y sí. Sus hallazgos para el método 'stringFromHex' es lo que estaba buscando también. ¿Puedo saber de dónde obtienes ese método y hay un tutorial sobre él? Me gustaría entender ese método, y no puedo analizarlo por mi cuenta. Gracias. –

+0

Lo siento, ha pasado demasiado tiempo, ya no recuerdo. –

Respuesta

21

Para estas líneas de Java

utf8 = s.getBytes(ENCODING_UTF8); 
new String(decodedHexString, ENCODING_UTF8); 

Objective-C equivalentes serían

utf8 = [s UTF8String]; 
[NSString initWithUTF8String:decodedHexString]; 

Haciendo NSString con la representación hexadecimal de una cadena de caracteres:

NSMutableString *hex = [NSMutableString string]; 
while (*utf8) [hex appendFormat:@"%02X" , *utf8++ & 0x00FF]; 

Usted tendrá que hacer su propia función decodeHex. Simplemente retire dos caracteres de la cadena y, si son válidos, agregue un byte al resultado.

+2

Debe ser "NSMutableString * hex = [cadena NSMutableString];" – Berik

-1

tal vez debería utilizar NSStringdataUsingEncoding: para codificar y decodificar initWithData:length:encoding: a. Depende de dónde obtengas los datos.

1

Así que, en primer lugar, me gustaría dar las gracias a drawnonward por su respuesta. Esto me dio la primera función, mala y limpia. En el mismo espíritu, escribí el otro. Espero que te guste.

@synthesize unsigned char* value= _value; 

- (NSString*) hexString 
{ 
    _value[CONSTANT]= '\0'; 
    unsigned char* ptr= _value; 

    NSMutableString* hex = [[NSMutableString alloc] init]; 
    while (*ptr) [hex appendFormat:@"%02x", *ptr++ & 0x00FF]; 

    return [hex autorelease]; 
} 

- (void) setHexString:(NSString*)hexString 
{ 
    _value[CONSTANT]= '\0'; 
    unsigned char* ptr= _value; 

    for (const char* src= [hexString cStringUsingEncoding:NSASCIIStringEncoding]; 
     *src; 
     src+=2) 
    { 
     unsigned int hexByte; 
     /*int res=*/ sscanf(src,"%02x",&hexByte); 
     *ptr++= (unsigned char)(hexByte & 0x00FF); 
    } 
    *ptr= '\0'; 
} 
8

Hay un problema con su método stringToHex - descarta los 0s principales e ignora los 00s. Justo como una solución rápida, hice lo siguiente:

+ (NSString *) stringToHex:(NSString *)str 
{ 
    NSUInteger len = [str length]; 
    unichar *chars = malloc(len * sizeof(unichar)); 
    [str getCharacters:chars]; 

    NSMutableString *hexString = [[NSMutableString alloc] init]; 

    for(NSUInteger i = 0; i < len; i++) 
    { 
     // [hexString [NSString stringWithFormat:@"%02x", chars[i]]]; /*previous input*/ 
     [hexString appendFormat:@"%02x", chars[i]]; /*EDITED PER COMMENT BELOW*/ 
    } 
    free(chars); 

    return [hexString autorelease]; 
} 
+0

No me di cuenta de eso. Pudo haber causado errores raros al azar que no sabía que existían. ¡Gracias! –

+3

Por cierto, hay un pequeño error en su código, '[hexString [NSString stringWithFormat: @"% 02x ", chars [i]]]' debe ser '[hexString appendString: [NSString stringWithFormat: @"% 02x ", chars [i ]]]; 'o incluso mejor' [hexString appendFormat: @ "% 02x", chars [i]]; ' –

+0

Aún no tengo privilegios de edición, así que no puedo editar tu respuesta con la corrección. –

6

Gracias a todos los que contribuyeron en este hilo. Fue una gran ayuda para mí. Como las cosas se han movido un poco desde la publicación original, aquí está mi implementación actualizada para iOS 6. Fui con el enfoque de categorías, pero decidí dividir la carga entre NSData y NSString. Comentarios bienvenidos.

Primero, la mitad NSString, que maneja la decodificación de una cadena codificada hexadecimal en un objeto NSData.

@implementation NSString (StringToHexData) 

// 
// Decodes an NSString containing hex encoded bytes into an NSData object 
// 
- (NSData *) stringToHexData 
{ 
    int len = [self length]/2; // Target length 
    unsigned char *buf = malloc(len) 
    unsigned char *whole_byte = buf; 
    char byte_chars[3] = {'\0','\0','\0'}; 

    int i; 
    for (i=0; i < [self length]/2; i++) { 
     byte_chars[0] = [self characterAtIndex:i*2]; 
     byte_chars[1] = [self characterAtIndex:i*2+1]; 
     *whole_byte = strtol(byte_chars, NULL, 16); 
     whole_byte++; 
    } 

    NSData *data = [NSData dataWithBytes:buf length:len]; 
    free(buf); 
    return data; 
} 
@end 

Los cambios eran en su mayoría por el bien de la eficiencia: un poco de aritmética simple puntero anticuada significa que pude asignar el búfer entero de una sola vez, y poblarlo byte a byte. Luego todo se pasa a NSData de una vez.

La parte de codificación, en NSData, se ve así:

@implementation NSData (DataToHexString) 

- (NSString *) dataToHexString 
{ 
    NSUInteger   len = [self length]; 
    char *    chars = (char *)[self bytes]; 
    NSMutableString * hexString = [[NSMutableString alloc] init]; 

    for(NSUInteger i = 0; i < len; i++) 
     [hexString appendString:[NSString stringWithFormat:@"%0.2hhx", chars[i]]]; 

    return hexString; 
} 
@end 

Una vez más, algunos cambios de menor importancia, aunque sospecho que no hay aumento de la eficiencia aquí. El uso de "% 0.2hhx" resolvió todos los problemas de falta de cero inicial y garantiza que solo se produzca un byte único a la vez.

Espero que esto ayude a la próxima persona que tome esto!

27

La forma perfecta y corta para convertir NSString a valores hexadecimales

NSMutableString *tempHex=[[NSMutableString alloc] init]; 

[tempHex appendString:@"0xD2D2D2"]; 

unsigned colorInt = 0; 

[[NSScanner scannerWithString:tempHex] scanHexInt:&colorInt]; 

lblAttString.backgroundColor=UIColorFromRGB(colorInt); 

La macro se utiliza para este código es ----

#define UIColorFromRGB(rgbValue) 
[UIColor \colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ 
green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \ 
blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] 
+1

Quizás agregar su implementación de la macro UIColorFromRGB junto con su respuesta. –

+0

Hola @JasperBlues he actualizado mi publicación con la macro requerida. – Prasanna

3

Una posible solución:

+(NSString*)hexFromStr:(NSString*)str 
{ 
    NSData* nsData = [str dataUsingEncoding:NSUTF8StringEncoding]; 
    const char* data = [nsData bytes]; 
    NSUInteger len = nsData.length; 
    NSMutableString* hex = [NSMutableString string]; 
    for(int i = 0; i < len; ++i)[hex appendFormat:@"%02X", data[i]]; 
    return hex; 
} 
+0

'const' es incorrecto aquí. –

0

Mi entrada fue una cadena de dígito base10, y la salida debe ser la representación hexadecimal en formato de cadena. Ejemplos:

  • @ "10" -> @ "A"
  • @ "1128" -> @ "468"
  • @ "1833828235" -> @ "6D4DFF8B"

implementación:

+ (NSString *) stringToHex:(NSString *)str{ 
NSInteger result = [str integerValue]; 
NSString *hexStr = (result)[email protected]"":@"0"; 

while (result!=0) { 
    NSInteger reminder = result % 16; 

    if(reminder>=0 && reminder<=9){ 
     hexStr = [[NSString stringWithFormat:@"%ld",(long)reminder] stringByAppendingString:hexStr]; 
    }else if(reminder==10){ 
     hexStr = [@"A" stringByAppendingString:hexStr]; 
    }else if(reminder==11){ 
     hexStr = [@"B" stringByAppendingString:hexStr]; 
    }else if(reminder==12){ 
     hexStr = [@"C" stringByAppendingString:hexStr]; 
    }else if(reminder==13){ 
     hexStr = [@"D" stringByAppendingString:hexStr]; 
    }else if(reminder==14){ 
     hexStr = [@"E" stringByAppendingString:hexStr]; 
    }else{ 
     hexStr = [@"F" stringByAppendingString:hexStr]; 
    } 

    result /=16; 
} 

return hexStr; 

}