2010-06-16 19 views
26

Mi piacerebbe convertire un normale NSString in un NSString con i valori esadecimali ASCII (cosa presumo siano) e indietro.Come convertire una NSString in valori esadecimali

Ho bisogno di produrre lo stesso output dei metodi Java riportati di seguito, ma non riesco a trovare un modo per farlo in Objective-C. Ho trovato alcuni esempi in C e C++ ma ho avuto difficoltà a lavorarli nel mio codice.

Ecco i metodi Java che sto cercando di riprodurre:

/** 
* 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); 
} 

Update: Grazie alla drawnonward di risposta qui è il metodo che ho scritto per creare le NSStrings esagonali. Mi dà un avvertimento "Inizializzazione rigetti di qualificatori dal tipo di puntatore" sulla riga della dichiarazione del carico, ma funziona.

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

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

Non ho ancora avuto il tempo di scrivere il metodo di decodifica. Quando lo faccio, lo modifico per postarlo per chiunque sia interessato.

Update2: Quindi il metodo che ho postato sopra in realtà non produce quello che sto cercando. Invece di emettere valori esadecimali nel formato 0-f, stava invece emettendo tutti i numeri. Finalmente sono tornato a lavorare su questo problema ed è stato in grado di scrivere una categoria per NSString che duplica esattamente i metodi Java che ho postato. Eccolo:

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

ho questo codice a casa. Lo posterò quando scendo dal lavoro a meno che qualcuno non mi picchi. –

+0

Ciao, so che questo è un vecchio post. Ma ho incontrato il tuo problema che ho affrontato e sì. Le tue scoperte per il metodo 'stringFromHex' sono quelle che stavo cercando anche io. Posso sapere da dove ottieni questo metodo e c'è un tutorial su di esso? Mi piacerebbe capire quel metodo e non posso analizzarlo da solo. Grazie. –

+0

Scusa è passato troppo tempo, non ricordo più. –

risposta

21

Per queste linee di Java

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

Objective-C equivalenti sarebbero

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

Per effettuare una NSString con la rappresentazione esadecimale di una stringa di caratteri:

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

È dovrà creare la propria funzione decodeHex. Basta estrarre due caratteri dalla stringa e, se sono validi, aggiungere un byte al risultato.

+2

Dovrebbe essere "NSMutableString * hex = [stringa NSMutableString];" – Berik

-1

forse si dovrebbe usare NSStringdataUsingEncoding: per codificare e decodificare initWithData:length:encoding: a. Dipende da dove stai ricevendo i dati.

1

Quindi, prima di tutto, vorrei ringraziare lo drawnonward per la sua risposta. Questo mi ha dato la prima funzione, cattiva e pulita. Nello stesso spirito, ho scritto l'altro. Spero ti piaccia.

@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

C'è un problema con il metodo stringToHex, che cade 0s iniziali e ignora 00s. Proprio come una soluzione rapida, ho fatto il seguente:

+ (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

Non me ne sono reso conto. Potrebbe aver causato rari bug casuali che non sapevo esistessero. Grazie! –

+3

Btw c'è un piccolo bug nel codice, '[hexString [NSString stringWithFormat: @"% 02x ", chars [i]]];' dovrebbe essere '[hexString appendString: [NSString stringWithFormat: @"% 02x ", caratteri [i ]]]; 'o anche meglio' [hexString appendFormat: @ "% 02x", caratteri [i]]; ' –

+0

Non ho ancora i privilegi di modifica, quindi non posso modificare la risposta con la correzione. –

6

Grazie a tutti coloro che hanno contribuito a questa discussione. È stato di grande aiuto per me Dal momento che le cose si sono spostate un po 'dal post originale, ecco la mia implementazione aggiornata per iOS 6. Sono andato con l'approccio delle categorie, ma ho scelto di dividere il carico tra NSData e NSString. Commenti accolti

In primo luogo, la metà NSString, che gestisce la decodifica di una stringa codificata esadecimale in un oggetto 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 

I cambiamenti erano principalmente per la propria efficienza: alcuni semplici puntatori antiquata significa ho potuto allocare l'intero buffer in una sola volta, e popolarla byte per byte. Quindi il tutto viene passato a NSData in un colpo solo.

La parte di codifica, in NSData, si presenta così:

@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 

Anche in questo caso, alcune piccole modifiche, anche se ho il sospetto che non guadagni di efficienza qui. L'uso di "% 0,2hhx" ha risolto tutti i problemi di zero iniziale mancanti e assicura che venga emesso un solo byte alla volta.

Spero che questo aiuti la persona successiva a fare questo!

27

Il modo perfetto e corto per convertire NSString valori esadecimali

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

[tempHex appendString:@"0xD2D2D2"]; 

unsigned colorInt = 0; 

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

lblAttString.backgroundColor=UIColorFromRGB(colorInt); 

La macro utilizzata per questo codice è ----

#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

Forse aggiungere la tua implementazione della macro UIColorFromRGB insieme alla tua risposta –

+0

Ciao @JasperBlues ho aggiornato il mio post con la macro richiesta. – Prasanna

3

Una possibile soluzione:

+(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' è improprio qui. –

0

Il mio input era una cifra base10 e l'output dovrebbe essere la rappresentazione esadecimale in formato stringa. Esempi:

  • @ "10" -> @ "A"
  • @ "1128" -> @ "468"
  • @ "1.833.828,235 mila" -> @ "6D4DFF8B"

implementazione:

+ (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; 

}

Problemi correlati