objective-c 将十六进制数据字符串转换为 Objective C (cocoa) 中的 NSData

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2338975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 23:09:26  来源:igfitidea点击:

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

iphoneobjective-ccocoahexnsdata

提问by Max Clarke

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.

相当新的 iPhone 开发者在这里。构建一个应用程序,通过 TCP/IP 套接字连接将 RS232 命令发送到设备。我已经解决了通信部分,并且可以很好地发送 ASCII 命令。这是我遇到问题的十六进制代码命令。

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

所以假设我有以下十六进制数据要发送(以这种格式):

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

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

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

如何将其转换为我的 send 方法所期望的 NSData 对象?

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

显然这不适用于此十六进制数据(但适用于标准 ascii 命令):

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.

首先,一些 \x 十六进制代码是转义字符,在 XCode 中编译时,我收到“输入转换已停止...”警告。NSStringEncoding 显然也不适合这个十六进制字符串。

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

所以第一个问题是我猜如何存储这个十六进制字符串,然后如何转换为NSData。

Any ideas?

有任何想法吗?

回答by Max Clarke

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

NSStrings 中的十六进制代码,如“00 05 22 1C EA 01 00 FF”。'command' 是十六进制 NSString。

command = [command stringByReplacingOccurrencesOfString:@" " withString:@""];
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'
#import <stdio.h>
#import <stdlib.h>
#import <string.h>

unsigned char strToChar (char a, char b)
{
    char encoder[3] = {'
const char bytes[] = "\x00\x12\x45\xAB";
size_t length = (sizeof bytes) - 1; //string literals have implicit trailing '

#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];
}
' NSData *data = [NSData dataWithBytes:bytes length:length];
','
+(NSData*)bytesStringToData:(NSString*)bytesString
{
    if (!bytesString || !bytesString.length) return NULL;
    // Get the c string
    const char *scanner=[bytesString cStringUsingEncoding:NSUTF8StringEncoding];
    char twoChars[3]={0,0,0};
    long bytesBlockSize = formattedBytesString.length/2;
    long counter = bytesBlockSize;
    Byte *bytesBlock = malloc(bytesBlockSize);
    if (!bytesBlock) return NULL;
    Byte *writer = bytesBlock;
    while (counter--) {
        twoChars[0]=*scanner++;
        twoChars[1]=*scanner++;
        *writer++ = strtol(twoChars, NULL, 16);
    }
    return[NSData dataWithBytesNoCopy:bytesBlock length:bytesBlockSize freeWhenDone:YES];
}
','
enum { numCommandBytes = 8 };
static const unsigned char commandBytes[numCommandBytes] = { 0x1c, 0x02, 'd', 0x0, 0x0, 0x0, 0xff, 0x7f };
'}; 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 = '
NSString *commandascii;
NSData *commandToSend;
commandascii = @"\x1C\x02d\x00\x00\x00\xFF\x7F";
commandToSend = [commandascii dataUsingEncoding:NSStringEncoding];
'; NSData * result = [NSData dataWithBytes: r length: length / 2]; free(r); return result; } @end
','
NSString *commandascii;
NSData *commandToSend;
commandascii = @"\x1C\x02d\x00\x00\x00\xFF\x7F";
commandToSend = [commandascii dataUsingEncoding:NSStringEncoding];
','
-(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;
}
'}; 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);

回答by xyzzycoder

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

这是在 NSString 上的类别上实现的示例解码器。

-(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] = {'
[[NSData alloc] initWithData:[stringToBeConverted dataUsingEncoding:NSASCIIStringEncoding]];
','
NSMutableData *hexData = [[NSMutableData alloc] init];

[hexData appendBytes: 0x1C];
[hexData appendBytes: 0x02D];
','##代码##'}; 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; }

回答by dreamlax

If you can hard code the hex data:

如果您可以对十六进制数据进行硬编码:

##代码##

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

如果您的代码必须解释十六进制字符串(假设十六进制字符串在名为 的变量中inputData并且lengthOfInputData是 的长度inputData):

##代码##

回答by Moose

This is an old topic, but I'd like to add some remarks.

这是一个老话题,但我想补充一些评论。

? Scanning a string with [NSString characterAtIndex]is not very efficient. Get the C string in UTF8, then scan it using a *char++is much faster.

? 用 扫描字符串[NSString characterAtIndex]效率不高。获取 UTF8 格式的 C 字符串,然后使用 a 扫描它*char++要快得多。

? It's better to allocate NSMutableDatawith capacity, to avoid time consuming block resizing. I think NSData is even better ( see next point )

? 最好按NSMutableData容量分配,以避免耗时的块调整大小。我认为 NSData 更好(见下一点)

? Instead of create NSData using malloc, then [NSData dataWithBytes]and finally free, use malloc, and [NSData dataWithBytesNoCopy:length:freeWhenDone:]

? 而不是使用 malloc 创建 NSData,然后[NSData dataWithBytes]最后释放,使用 malloc,然后[NSData dataWithBytesNoCopy:length:freeWhenDone:]

It also avoids memory operation ( reallocate, copy, free ). The freeWhenDone boolean tells the NSData to take ownership of the memory block, and free it when it will be released.

它还避免了内存操作(重新分配、复制、释放)。freeWhenDone 布尔值告诉 NSData 获取内存块的所有权,并在它被释放时释放它。

? Here is the function I have to convert hex strings to bytes blocks. There is not much error checking on input string, but the allocation is tested.

? 这是我必须将十六进制字符串转换为字节块的函数。对输入字符串没有太多错误检查,但测试了分配。

The formatting of the input string ( like remove 0x, spaces and punctuation marks ) is better out of the conversion function. Why would we lose some time doing extra processing if we are sure the input is OK.

输入字符串的格式(如删除 0x、空格和标点符号)更好地脱离了转换功能。如果我们确定输入没问题,为什么还要浪费一些时间做额外的处理。

##代码##

回答by Peter Hosey

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

如果我想对字节进行硬编码,我会这样做:

##代码##

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

如果你获得在运行时,这些反斜杠转义字节,尝试strunvis功能

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

##代码##

For a start, some of the \xhex 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.

显然这不适用于此十六进制数据(但适用于标准 ascii 命令):

##代码##

首先,一些\x十六进制代码是转义字符,在 XCode 中编译时,我收到“输入转换已停止...”警告。NSStringEncoding 显然也不适合这个十六进制字符串。

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

首先,它是 Xcode,带有小写的 c。

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

其次,NSStringEncoding是类型,而不是编码标识符。该代码根本不应该编译。

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.

更重要的是,反斜杠转义不是一种编码;事实上,它在很大程度上独立于编码。反斜杠和 'x' 是字符,而不是字节,这意味着它们必须编码为(和解码)字节,这是编码的工作。

回答by Amit

Another way to do it.

另一种方法来做到这一点。

##代码##

回答by Karim Mousa

##代码##

回答by Markandaiya

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.

我知道这是一个非常古老的线程,但是 Objective C 中有一种编码方案可以轻松地将您的十六进制代码字符串转换为 ASCII 字符。

1) remove the \xfrom the string and with out keeping spaces in the string just convert the string to NSDatausing :

1)\x从字符串中删除,并且在字符串中不保留空格,只需将字符串转换为NSDatausing :

##代码##

回答by Bruce Johnson

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)

十六进制数据只是内存中的字节,您可以将其视为字符串,因为这就是您看到的方式,但它们可以表示任何内容。尝试:(在浏览器中输入,可能有错误)

##代码##

etc...

等等...