Converting HEX NSString To NSData
Solution 1
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);
Solution 2
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
Solution 3
This might be more useful, Apple has shared a NSData category.
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
Solution 4
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;
}
Pranav Jaiswal
Senior software engineer specialized in app development for iOS. Writing, debugging, optimizing, and architecting the code that powers the apps we love to use is what I do all day. My ability to communicate complex concepts, to come up with best-of-breed solutions, and execute these solutions in time to strategic problems are someone things that can bring immediate value and impact in the shortest period of time to a project. I have proven ability to drive a project from ground-up to completion and get software shipped. #SOreadytohelp
Updated on July 09, 2022Comments
-
Pranav Jaiswal almost 2 years
I'm trying to convert a Hex
NSString
toNSData
(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);
-
Praveen S over 12 yearsShould you not pass 16 to strtol?
-
-
Pranav Jaiswal over 12 yearswhat's the output that you are getting?
-
Nikunj Jadav over 12 yearsits returns <72ff63ce a198b3ed ba8f7e0c 23acc345 050187a0 cde5a987 2cbab091 ab73e553>
-
Pranav Jaiswal over 12 yearsone more ques whole_byte = strtol(byte_chars, NULL, 16); why the third param is passed as 16 Constant?
-
MikeS over 10 yearsNice answer. Useful for converting NSData deviceToken descriptions back into NSData.
-
Moxarth over 6 yearsit 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 = <ffff0215 e84a40af 7b8de88d 4a7b40af afe84a40 40af7b8d c3>; ` 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 over 6 years@NikunjJadav even i have raised the question for this [stackoverflow.com/questions/45854508/… . please look into it and guide me through it . thanks .
-
Benny Davidovitz over 5 yearsmemory dynamically allocated by call to
malloc()
at ... is not reachable after line .... > return [NSData dataWithBytesNoCopy:bytes length:[hex length]/2 freeWhenDone:YES];