44

I'm trying to convert a Hex NSString to NSData (I'm using the below attached code). The following is the output:

<00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000>

which looks totally irrelevant to me. Any idea/ suggestions on where its going wrong?

NSString *strData = @"72ff63cea198b3edba8f7e0c23acc345050187a0cde5a9872cbab091ab73e553";

NSLog(@"string Data length is %d",[strData length]);

NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[2];
int i;
for (i=0; i < [strData length]/2; i++) {

    byte_chars[0] = [strData characterAtIndex:i*2];
    byte_chars[1] = [strData characterAtIndex:i*2+1];
    whole_byte = strtol(byte_chars, NULL, [strData length]);
    [commandToSend appendBytes:&whole_byte length:1]; 
}
NSLog(@"%@", commandToSend);    
Regexident
  • 29,441
  • 10
  • 93
  • 100
Pranav Jaiswal
  • 3,752
  • 3
  • 32
  • 50

4 Answers4

70
NSString *command = @"72ff63cea198b3edba8f7e0c23acc345050187a0cde5a9872cbab091ab73e553";

command = [command stringByReplacingOccurrencesOfString:@" " withString:@""];
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [command length]/2; i++) {
    byte_chars[0] = [command characterAtIndex:i*2];
    byte_chars[1] = [command characterAtIndex:i*2+1];
    whole_byte = strtol(byte_chars, NULL, 16);
    [commandToSend appendBytes:&whole_byte length:1]; 
}
NSLog(@"%@", commandToSend);
Filip Radelic
  • 26,607
  • 8
  • 71
  • 97
Nikunj Jadav
  • 3,417
  • 7
  • 38
  • 54
  • 1
    what's the output that you are getting? – Pranav Jaiswal Sep 06 '11 at 10:02
  • 2
    its returns <72ff63ce a198b3ed ba8f7e0c 23acc345 050187a0 cde5a987 2cbab091 ab73e553> – Nikunj Jadav Sep 06 '11 at 10:09
  • one more ques whole_byte = strtol(byte_chars, NULL, 16); why the third param is passed as 16 Constant? – Pranav Jaiswal Sep 06 '11 at 10:19
  • 4
    Nice answer. Useful for converting NSData deviceToken descriptions back into NSData. – MikeS Nov 21 '13 at 23:13
  • it looks like in answer we are getting the same answer as what we have given string to convert . ? but how to convert that string data into informative one ? i mean after scanning for BLE device , i got the advertisement data like ` kCBAdvDataManufacturerData = ; ` this . so now from this , how to convert ,in order to access its data . i supposed to find out Major Minor TxPower from this given data ,. how can we do this ? @NikunjJadav – Moxarth Aug 26 '17 at 06:17
  • @NikunjJadav even i have raised the question for this [https://stackoverflow.com/questions/45854508/how-to-decode-the-ble-advertisement-data/45859742?noredirect=1#comment78727814_45859742] . please look into it and guide me through it . thanks . – Moxarth Aug 26 '17 at 06:18
31

Here is another method that also handles leading <, trailing > and embedded spaces such as

<9dc69faf a7434ba9 aef57f5c 365d571f 4c3753c4 ae13db42 57d184ca e00246c5>

Code:

+ (NSData *)dataFromHexString:(NSString *)string
{
    string = [string lowercaseString];
    NSMutableData *data= [NSMutableData new];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    int i = 0;
    int length = string.length;
    while (i < length-1) {
        char c = [string characterAtIndex:i++];
        if (c < '0' || (c > '9' && c < 'a') || c > 'f')
            continue;
        byte_chars[0] = c;
        byte_chars[1] = [string characterAtIndex:i++];
        whole_byte = strtol(byte_chars, NULL, 16);
        [data appendBytes:&whole_byte length:1];
    }
    return data;
}

This is based on the answer by @Nikunj R. Jadav

ItalyPaleAle
  • 7,185
  • 6
  • 42
  • 69
zaph
  • 111,848
  • 21
  • 189
  • 228
8

This might be more useful, Apple has shared a NSData category.

NSData+HexString.m

The code is:

@implementation NSData (HexString)

// Not efficent
+(id)dataWithHexString:(NSString *)hex
{
    char buf[3];
    buf[2] = '\0';
    NSAssert(0 == [hex length] % 2, @"Hex strings should have an even number of digits (%@)", hex);
    unsigned char *bytes = malloc([hex length]/2);
    unsigned char *bp = bytes;
    for (CFIndex i = 0; i < [hex length]; i += 2) {
        buf[0] = [hex characterAtIndex:i];
        buf[1] = [hex characterAtIndex:i+1];
        char *b2 = NULL;
        *bp++ = strtol(buf, &b2, 16);
        NSAssert(b2 == buf + 2, @"String should be all hex digits: %@ (bad digit around %d)", hex, i);
    }

    return [NSData dataWithBytesNoCopy:bytes length:[hex length]/2 freeWhenDone:YES];
}

@end
DefenestrationDay
  • 3,712
  • 2
  • 33
  • 61
Shwet Solanki
  • 345
  • 3
  • 12
  • memory dynamically allocated by call to `malloc()` at ... is not reachable after line .... > return [NSData dataWithBytesNoCopy:bytes length:[hex length]/2 freeWhenDone:YES]; – Benny Davidovitz Jan 14 '19 at 22:11
1

I see several solution have been post only able to convert string with even length.

So here is my solution which also able return correct data if the string is odd length like this "DBA" became data like this this "\x0D\xBA"

+ (NSData *)dataFromHexString:(NSString *) string {
    if([string length] % 2 == 1){
        string = [@"0"stringByAppendingString:string];
    }

    const char *chars = [string UTF8String];
    int i = 0, len = (int)[string 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;

}
jefry jacky
  • 799
  • 7
  • 11