Convert hex data string to NSData in Objective C (cocoa)

后端 未结 9 1288
栀梦
栀梦 2020-12-03 11:55

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 s

相关标签:
9条回答
  • 2020-12-03 12:24

    I know this is a very old thread, but there is an encoding scheme in Objective C that can easily convert your string of hex codes into ASCII characters.

    1) remove the \x from the string and with out keeping spaces in the string just convert the string to NSData using :

    [[NSData alloc] initWithData:[stringToBeConverted dataUsingEncoding:NSASCIIStringEncoding]];
    
    0 讨论(0)
  • 2020-12-03 12:32

    Hex data is just bytes in memory, you think of it as a string because that's how you see it but they could represent anything. Try: (typed in the browser, may contain errors)

    NSMutableData *hexData = [[NSMutableData alloc] init];
    
    [hexData appendBytes: 0x1C];
    [hexData appendBytes: 0x02D];
    

    etc...

    0 讨论(0)
  • 2020-12-03 12:33

    If I want to hard-code the bytes, I do something like this:

    enum { numCommandBytes = 8 };
    static const unsigned char commandBytes[numCommandBytes] = { 0x1c, 0x02, 'd', 0x0, 0x0, 0x0, 0xff, 0x7f };
    

    If you're obtaining these backslash-escaped bytes at run time, try the strunvis function.

    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.

    First, it's Xcode, with a lowercase c.

    Second, NSStringEncoding is a type, not an encoding identifier. That code shouldn't compile at all.

    More to the point, backslash-escaping is not an encoding; in fact, it's largely independent of encoding. The backslash and 'x' are characters, not bytes, which means that they must be encoded to (and decoded from) bytes, which is the job of an encoding.

    0 讨论(0)
  • 2020-12-03 12:33

    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;
    }
    
    0 讨论(0)
  • 2020-12-03 12:34

    If you can hard code the hex data:

    const char bytes[] = "\x00\x12\x45\xAB";
    size_t length = (sizeof bytes) - 1; //string literals have implicit trailing '\0'
    
    NSData *data = [NSData dataWithBytes:bytes length:length];

    If your code must interpret the hex string (assuming the hex string is in a variable called inputData and lengthOfInputData is the length of inputData):

    
    #define HexCharToNybble(x) ((char)((x > '9') ? tolower(x) - 'a' + 10 : x - '0') & 0xF)
    
    int i;
    
    NSMutableData *data = [NSMutableData data];
    
    for (i = 0; i < lengthOfInputData;)
    {
        char byteToAppend;
    
        if (i < (lengthOfInputData - 3) &&
            inputData[i+0] == '\\' &&
            inputData[i+1] == 'x' &&
            isxdigit(inputData[i+2]) &&
            isxdigit(inputData[i+3]))
        {
            byteToAppend = HexCharToNybble(inputData[i+2]) << 4 + HexCharToNybble(input[i+3]);
            i += 4;
        }
        else
        {
            byteToAppend = inputData[i];
            i += 1;
        }
    
        [data appendBytes:&byteToAppend length:1];
    }
    0 讨论(0)
  • 2020-12-03 12:34
    -(NSData*) convertToByteArray:(NSString*) command {
        if (command == nil || command.length == 0) return nil;
        NSString *command1 = command;
        if(command1.length%2 != 0) {
            // to handle odd bytes like 1000 decimal = 3E8 with is of length = 3
            command1 = [NSString stringWithFormat:@"0%@",command1];
        }
        NSUInteger length = command1.length/2 ;
        NSMutableData *commandToSend = [[NSMutableData alloc] initWithLength:length];
        char byte_chars[3] = {'\0','\0','\0'};
        unsigned char whole_byte;
        for (int i=0; i<length; i++) {
            byte_chars[0] = [command1 characterAtIndex:i*2];
            byte_chars[1] = [command1 characterAtIndex:i*2+1];
            whole_byte = strtol(byte_chars, NULL, 16);
            [commandToSend appendBytes:&whole_byte length:1];
        }
        NSRange commandRange = NSMakeRange(commandToSend.length - length, length);
        NSData *result = [commandToSend subdataWithRange:commandRange];
        return result;
    }
    
    0 讨论(0)
提交回复
热议问题