Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSString (hex) to bytes

Is there any method in Objective-C that converts a hex string to bytes? For example @"1156FFCD3430AA22" to an unsigned char array {0x11, 0x56, 0xFF, ...}.

like image 460
AOO Avatar asked Mar 23 '10 15:03

AOO


4 Answers

Fastest NSString category implementation that I could think of (cocktail of some examples):

- (NSData *)dataFromHexString {
    const char *chars = [self UTF8String];
    int i = 0, len = self.length;

    NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
    char byteChars[3] = {'\0','\0','\0'};
    unsigned long wholeByte;

    while (i < len) {
        byteChars[0] = chars[i++];
        byteChars[1] = chars[i++];
        wholeByte = strtoul(byteChars, NULL, 16);
        [data appendBytes:&wholeByte length:1];
    }

    return data;
}

It is close to 8 times faster than wookay's solution. NSScanner is quite slow.

like image 60
Zyphrax Avatar answered Nov 13 '22 05:11

Zyphrax


@interface NSString (NSStringHexToBytes)
-(NSData*) hexToBytes ;
@end



@implementation NSString (NSStringHexToBytes)
-(NSData*) hexToBytes {
  NSMutableData* data = [NSMutableData data];
  int idx;
  for (idx = 0; idx+2 <= self.length; idx+=2) {
    NSRange range = NSMakeRange(idx, 2);
    NSString* hexStr = [self substringWithRange:range];
    NSScanner* scanner = [NSScanner scannerWithString:hexStr];
    unsigned int intValue;
    [scanner scanHexInt:&intValue];
    [data appendBytes:&intValue length:1];
  }
  return data;
}
@end



/// example
unsigned char bytes[] = { 0x11, 0x56, 0xFF, 0xCD, 0x34, 0x30, 0xAA, 0x22 };
NSData* expectedData = [NSData dataWithBytes:bytes length:sizeof(bytes)];
NSLog(@"data %@", [@"1156FFCD3430AA22" hexToBytes]);
NSLog(@"expectedData isEqual:%d", [expectedData isEqual:[@"1156FFCD3430AA22" hexToBytes]]);
like image 37
wookay Avatar answered Nov 13 '22 07:11

wookay


The scanHexInt: and similar methods of NSScanner might be helpful in doing what you want, but you'd probably need to break the string up into smaller chunks first, in which case doing the translation manually might be simpler than using NSScanner.

like image 3
Isaac Avatar answered Nov 13 '22 07:11

Isaac


Not in the way you are doing it. You'll need to write your own method to take every two characters, interpret them as an int, and store them in an array.

like image 2
Marc W Avatar answered Nov 13 '22 05:11

Marc W