Convert hex data string to NSData in Objective C (

2019-01-11 23:59发布

fairly new iPhone developer here. Building an app to send RS232 commands to a device expecting them over a TCP/IP socket connection. I've got the comms part down, and can send ASCII commands fine. It's the hex code commands I'm having trouble with.

So lets say I have the following hex data to send (in this format):

\x1C\x02d\x00\x00\x00\xFF\x7F

How do I convert this into an NSData object, which my send method expects?

Obviously this does not work for this hex data (but does for standard ascii commands):

NSString *commandascii;
NSData *commandToSend;
commandascii = @"\x1C\x02d\x00\x00\x00\xFF\x7F";
commandToSend = [commandascii dataUsingEncoding:NSStringEncoding];

For a start, some of the \x hex codes are escape characters, and I get an "input conversion stopped..." warning when compiling in XCode. And NSStringEncoding obviously isn't right for this hex string either.

So the first problem is how to store this hex string I guess, then how to convert to NSData.

Any ideas?

9条回答
Rolldiameter
2楼-- · 2019-01-12 00:53

Here's an example decoder implemented on a category on NSString.

#import <stdio.h>
#import <stdlib.h>
#import <string.h>

unsigned char strToChar (char a, char b)
{
    char encoder[3] = {'\0','\0','\0'};
    encoder[0] = a;
    encoder[1] = b;
    return (char) strtol(encoder,NULL,16);
}

@interface NSString (NSStringExtensions)
- (NSData *) decodeFromHexidecimal;
@end

@implementation NSString (NSStringExtensions)

- (NSData *) decodeFromHexidecimal;
{
    const char * bytes = [self cStringUsingEncoding: NSUTF8StringEncoding];
    NSUInteger length = strlen(bytes);
    unsigned char * r = (unsigned char *) malloc(length / 2 + 1);
    unsigned char * index = r;

    while ((*bytes) && (*(bytes +1))) {
        *index = strToChar(*bytes, *(bytes +1));
        index++;
        bytes+=2;
    }
    *index = '\0';

    NSData * result = [NSData dataWithBytes: r length: length / 2];
    free(r);

    return result;
}

@end
查看更多
Explosion°爆炸
3楼-- · 2019-01-12 00:58

Another way to do it.

-(NSData *) dataFromHexString:(NSString *) hexstr
{
    NSMutableData *data = [[NSMutableData alloc] init];
    NSString *inputStr = [hexstr uppercaseString];

    NSString *hexChars = @"0123456789ABCDEF";

    Byte b1,b2;
    b1 = 255;
    b2 = 255;
    for (int i=0; i<hexstr.length; i++) {
        NSString *subStr = [inputStr substringWithRange:NSMakeRange(i, 1)];
        NSRange loc = [hexChars rangeOfString:subStr];

        if (loc.location == NSNotFound) continue;

        if (255 == b1) {
            b1 = (Byte)loc.location;
        }else {
            b2 = (Byte)loc.location;

            //Appending the Byte to NSData
            Byte *bytes = malloc(sizeof(Byte) *1);
            bytes[0] = ((b1<<4) & 0xf0) | (b2 & 0x0f);
            [data appendBytes:bytes length:1];

            b1 = b2 = 255;
        }
    }

    return data;
}
查看更多
手持菜刀,她持情操
4楼-- · 2019-01-12 00:59

Code for hex in NSStrings like "00 05 22 1C EA 01 00 FF". 'command' is the hex NSString.

command = [command stringByReplacingOccurrencesOfString:@" " withString:@""];
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
for (int 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);
查看更多
登录 后发表回答