Преобразуйте шестнадцатеричную строку данных в NSData в Objective C (какао)

довольно новый разработчик iPhone здесь. Создание приложения для отправки команд RS232 в устройство, ожидая их по сокетному соединению TCP/IP. Я имею comms часть вниз и могу отправить прекрасные команды ASCII. Это - шестнадцатеричные команды кода, из-за которых я испытываю затруднения.

Так позволяет, говорят, что у меня есть следующие шестнадцатеричные данные для отправки (в этом формате):

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

Как я преобразовываю это в объект NSData, который мой отправлять метод ожидает?

Очевидно, это не работает на эти шестнадцатеричные данные (но делает для стандартных команд ASCII):

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

Для запуска некоторые шестнадцатеричные коды \x являются символами ESC, и я получаю "входное преобразование, остановленное..." предупреждая при компиляции в XCode. И NSStringEncoding, очевидно, не является правильным для этой шестнадцатеричной строки также.

Таким образом, первая проблема состоит в том, как сохранить эту шестнадцатеричную строку, которую я предполагаю, затем как преобразовать в NSData.

Какие-либо идеи?

10
задан Max Clarke 1 March 2010 в 01:40
поделиться

5 ответов

Шестнадцатеричный код в строках NSS, например «00 05 22 1C EA 01 00 FF». "команда" - это шестнадцатеричное 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);
30
ответ дан 3 December 2019 в 13:44
поделиться

Вот пример декодера, реализованного для категории в 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
9
ответ дан 3 December 2019 в 13:44
поделиться

Если вы можете жестко закодировать шестнадцатеричные данные:

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];

Если ваш код должен интерпретировать шестнадцатеричную строку (при условии, что шестнадцатеричная строка находится в переменной с именем inputData и lengthOfInputData - это длина 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];
}
4
ответ дан 3 December 2019 в 13:44
поделиться

Шестнадцатеричные данные - это просто байты в памяти, вы думаете о них как о строках, потому что так вы их видите, но они могут представлять что угодно. Попробуйте: (набрано в браузере, может содержать ошибки)

NSMutableData *hexData = [[NSMutableData alloc] init];

[hexData appendBytes: 0x1C];
[hexData appendBytes: 0x02D];

и т.д....

-3
ответ дан 3 December 2019 в 13:44
поделиться

Если я хочу жестко закодировать байты, я делаю примерно следующее:

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

Если вы получаете эти backslash-escaped байты во время выполнения, попробуйте функцию strunvis.

Очевидно, что она не работает для шестнадцатеричных данных (но работает для стандартных ascii команд):

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

Для начала, некоторые из \x шестнадцатеричных кодов являются управляющими символами, и я получаю предупреждение "преобразование ввода остановлено..." при компиляции в XCode. И NSStringEncoding явно не подходит для этой шестнадцатеричной строки.

Во-первых, это Xcode, со строчной буквы С.

Во-вторых, NSStringEncoding - это тип, а не идентификатор кодировки. Этот код вообще не должен компилироваться.

Более того, обратная косая черта не является кодировкой; на самом деле, она в значительной степени не зависит от кодировки. Обратная косая черта и 'x' - это символы, а не байты, что означает, что они должны быть закодированы в байты (и декодированы из них), что является задачей кодировки.

1
ответ дан 3 December 2019 в 13:44
поделиться