NSString(十六进制)到字节

发布于 2024-08-25 20:44:01 字数 126 浏览 6 评论 0原文

Objective-C 中是否有任何方法可以将十六进制字符串转换为字节?例如,@"1156FFCD3430AA22"无符号字符数组 {0x11, 0x56, 0xFF, ...}

Is there any method in Objective-C that converts a hex string to bytes? For example @"1156FFCD3430AA22" to an unsigned char array {0x11, 0x56, 0xFF, ...}.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

攒一口袋星星 2024-09-01 20:44:01

我能想到的最快的 NSString 类别实现(一些示例的混合物):

- (NSData *)dataFromHexString {
    const char *chars = [self UTF8String];
    int i = 0, len = self.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;
}

它比 wookay 的解决方案快了近 8 倍。 NSScanner 相当慢。

Fastest NSString category implementation that I could think of (cocktail of some examples):

- (NSData *)dataFromHexString {
    const char *chars = [self UTF8String];
    int i = 0, len = self.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;
}

It is close to 8 times faster than wookay's solution. NSScanner is quite slow.

野稚 2024-09-01 20:44:01
@interface NSString (NSStringHexToBytes)
-(NSData*) hexToBytes ;
@end



@implementation NSString (NSStringHexToBytes)
-(NSData*) hexToBytes {
  NSMutableData* data = [NSMutableData data];
  int idx;
  for (idx = 0; idx+2 <= self.length; idx+=2) {
    NSRange range = NSMakeRange(idx, 2);
    NSString* hexStr = [self substringWithRange:range];
    NSScanner* scanner = [NSScanner scannerWithString:hexStr];
    unsigned int intValue;
    [scanner scanHexInt:&intValue];
    [data appendBytes:&intValue length:1];
  }
  return data;
}
@end



/// example
unsigned char bytes[] = { 0x11, 0x56, 0xFF, 0xCD, 0x34, 0x30, 0xAA, 0x22 };
NSData* expectedData = [NSData dataWithBytes:bytes length:sizeof(bytes)];
NSLog(@"data %@", [@"1156FFCD3430AA22" hexToBytes]);
NSLog(@"expectedData isEqual:%d", [expectedData isEqual:[@"1156FFCD3430AA22" hexToBytes]]);
@interface NSString (NSStringHexToBytes)
-(NSData*) hexToBytes ;
@end



@implementation NSString (NSStringHexToBytes)
-(NSData*) hexToBytes {
  NSMutableData* data = [NSMutableData data];
  int idx;
  for (idx = 0; idx+2 <= self.length; idx+=2) {
    NSRange range = NSMakeRange(idx, 2);
    NSString* hexStr = [self substringWithRange:range];
    NSScanner* scanner = [NSScanner scannerWithString:hexStr];
    unsigned int intValue;
    [scanner scanHexInt:&intValue];
    [data appendBytes:&intValue length:1];
  }
  return data;
}
@end



/// example
unsigned char bytes[] = { 0x11, 0x56, 0xFF, 0xCD, 0x34, 0x30, 0xAA, 0x22 };
NSData* expectedData = [NSData dataWithBytes:bytes length:sizeof(bytes)];
NSLog(@"data %@", [@"1156FFCD3430AA22" hexToBytes]);
NSLog(@"expectedData isEqual:%d", [expectedData isEqual:[@"1156FFCD3430AA22" hexToBytes]]);
爱本泡沫多脆弱 2024-09-01 20:44:01

scanHexInt:NSScanner 的类似方法可能有助于执行您想要的操作,但您可能需要打破首先将其串成较小的块,在这种情况下,手动进行翻译可能比使用 NSScanner 更简单。

The scanHexInt: and similar methods of NSScanner might be helpful in doing what you want, but you'd probably need to break the string up into smaller chunks first, in which case doing the translation manually might be simpler than using NSScanner.

思慕 2024-09-01 20:44:01

不是以你正在做的方式。您需要编写自己的方法来获取每两个字符,将它们解释为 int,并将它们存储在数组中。

Not in the way you are doing it. You'll need to write your own method to take every two characters, interpret them as an int, and store them in an array.

行雁书 2024-09-01 20:44:01

修改方法,

/* Converts a hex string to bytes.
 Precondition:
 . The hex string can be separated by space or not.
 . the string length without space or 0x, must be even. 2 symbols for one byte/char
 . sample input: 23 3A F1 OR 233AF1, 0x23 0X231f 2B
 */

+ (NSData *) dataFromHexString:(NSString*)hexString
{
    NSString * cleanString = [Util cleanNonHexCharsFromHexString:hexString];
    if (cleanString == nil) {
        return nil;
    }

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

    int i = 0;
    for (i = 0; i+2 <= cleanString.length; i+=2) {
        NSRange range = NSMakeRange(i, 2);
        NSString* hexStr = [cleanString substringWithRange:range];
        NSScanner* scanner = [NSScanner scannerWithString:hexStr];
        unsigned int intValue;
        [scanner scanHexInt:&intValue];
        unsigned char uc = (unsigned char) intValue;
        [result appendBytes:&uc length:1];
    }
    NSData * data = [NSData dataWithData:result];
    [result release];
    return data;
}

/* Clean a hex string by removing spaces and 0x chars.
 . The hex string can be separated by space or not.
 . sample input: 23 3A F1; 233AF1; 0x23 0x3A 0xf1
 */

+ (NSString *) cleanNonHexCharsFromHexString:(NSString *)input
{
    if (input == nil) {
        return nil;
    }

    NSString * output = [input stringByReplacingOccurrencesOfString:@"0x" withString:@""
                                    options:NSCaseInsensitiveSearch range:NSMakeRange(0, input.length)];
    NSString * hexChars = @"0123456789abcdefABCDEF";
    NSCharacterSet *hexc = [NSCharacterSet characterSetWithCharactersInString:hexChars];
    NSCharacterSet *invalidHexc = [hexc invertedSet];
    NSString * allHex = [[output componentsSeparatedByCharactersInSet:invalidHexc] componentsJoinedByString:@""];
    return allHex;
}

Modified approach,

/* Converts a hex string to bytes.
 Precondition:
 . The hex string can be separated by space or not.
 . the string length without space or 0x, must be even. 2 symbols for one byte/char
 . sample input: 23 3A F1 OR 233AF1, 0x23 0X231f 2B
 */

+ (NSData *) dataFromHexString:(NSString*)hexString
{
    NSString * cleanString = [Util cleanNonHexCharsFromHexString:hexString];
    if (cleanString == nil) {
        return nil;
    }

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

    int i = 0;
    for (i = 0; i+2 <= cleanString.length; i+=2) {
        NSRange range = NSMakeRange(i, 2);
        NSString* hexStr = [cleanString substringWithRange:range];
        NSScanner* scanner = [NSScanner scannerWithString:hexStr];
        unsigned int intValue;
        [scanner scanHexInt:&intValue];
        unsigned char uc = (unsigned char) intValue;
        [result appendBytes:&uc length:1];
    }
    NSData * data = [NSData dataWithData:result];
    [result release];
    return data;
}

/* Clean a hex string by removing spaces and 0x chars.
 . The hex string can be separated by space or not.
 . sample input: 23 3A F1; 233AF1; 0x23 0x3A 0xf1
 */

+ (NSString *) cleanNonHexCharsFromHexString:(NSString *)input
{
    if (input == nil) {
        return nil;
    }

    NSString * output = [input stringByReplacingOccurrencesOfString:@"0x" withString:@""
                                    options:NSCaseInsensitiveSearch range:NSMakeRange(0, input.length)];
    NSString * hexChars = @"0123456789abcdefABCDEF";
    NSCharacterSet *hexc = [NSCharacterSet characterSetWithCharactersInString:hexChars];
    NSCharacterSet *invalidHexc = [hexc invertedSet];
    NSString * allHex = [[output componentsSeparatedByCharactersInSet:invalidHexc] componentsJoinedByString:@""];
    return allHex;
}
咆哮 2024-09-01 20:44:01

Swift 2.2 中的首次尝试:

func hexStringToBytes(hexString: String) -> NSData? {
    guard let chars = hexString.cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
    var i = 0
    let length = hexString.characters.count

    let data = NSMutableData(capacity: length/2)
    var byteChars: [CChar] = [0, 0, 0]

    var wholeByte: CUnsignedLong = 0

    while i < length {
        byteChars[0] = chars[i]
        i+=1
        byteChars[1] = chars[i]
        i+=1
        wholeByte = strtoul(byteChars, nil, 16)
        data?.appendBytes(&wholeByte, length: 1)
    }

    return data
}

或者,作为 String 的扩展:

extension String {

    func dataFromHexString() -> NSData? {
        guard let chars = cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
        var i = 0
        let length = characters.count

        let data = NSMutableData(capacity: length/2)
        var byteChars: [CChar] = [0, 0, 0]

        var wholeByte: CUnsignedLong = 0

        while i < length {
            byteChars[0] = chars[i]
            i+=1
            byteChars[1] = chars[i]
            i+=1
            wholeByte = strtoul(byteChars, nil, 16)
            data?.appendBytes(&wholeByte, length: 1)
        }

        return data
    }
}

这是一项持续进行中的工作,但到目前为止似乎运行良好。

进一步的优化和更深入的讨论可以在代码审查中找到。

First attempt in Swift 2.2:

func hexStringToBytes(hexString: String) -> NSData? {
    guard let chars = hexString.cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
    var i = 0
    let length = hexString.characters.count

    let data = NSMutableData(capacity: length/2)
    var byteChars: [CChar] = [0, 0, 0]

    var wholeByte: CUnsignedLong = 0

    while i < length {
        byteChars[0] = chars[i]
        i+=1
        byteChars[1] = chars[i]
        i+=1
        wholeByte = strtoul(byteChars, nil, 16)
        data?.appendBytes(&wholeByte, length: 1)
    }

    return data
}

Or, as an extension on String:

extension String {

    func dataFromHexString() -> NSData? {
        guard let chars = cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
        var i = 0
        let length = characters.count

        let data = NSMutableData(capacity: length/2)
        var byteChars: [CChar] = [0, 0, 0]

        var wholeByte: CUnsignedLong = 0

        while i < length {
            byteChars[0] = chars[i]
            i+=1
            byteChars[1] = chars[i]
            i+=1
            wholeByte = strtoul(byteChars, nil, 16)
            data?.appendBytes(&wholeByte, length: 1)
        }

        return data
    }
}

This is a continuous work-in-progress, but appears to work well so far.

Further optimizations and a more in-depth discussion can be found on Code Review.

难忘№最初的完美 2024-09-01 20:44:01

如果字符串像这样返回错误值的几种解决方案
DBA

DBA”字符串的正确数据为 “\x0D\xBA”(int 值:3514)

如果您获得了数据, 不是这样的“\x0D\xBA”这意味着你得到了一个错误的字节,因为值会不同,例如你得到了这样的数据“\xDB\x0A” > int 值为 56074

这里重写解决方案:

+ (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;

}

Several solution is returned wrong value if the string like this
"DBA"

The correct data for "DBA" string is "\x0D\xBA" (int value : 3514)

if you got a data is not like this "\x0D\xBA" it mean you got a wrong byte because the value will be different, for example you got data like this "\xDB\x0A" the int value is 56074

Here is rewrite the solution:

+ (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;

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文