如何将一个NSString转换为十六进制值

31

我想将普通的NSString转换为带有(我认为是)ASCII十六进制值的NSString,然后再将其转换回去。

我需要生成与以下Java方法相同的输出结果,但我似乎找不到在Objective-C中实现它的方法。我已经找到了一些在C和C ++中的例子,但我很难将它们融入我的代码中。

这里是我想要复制的Java方法:

/**
* Encodes the given string by using the hexadecimal representation of its UTF-8 bytes.
*
* @param s The string to encode.
* @return The encoded string.
*/
public static String utf8HexEncode(String s) {
    if (s == null) {
        return null;
    }
    byte[] utf8;
    try {
        utf8 = s.getBytes(ENCODING_UTF8);
    } catch (UnsupportedEncodingException x) {
        throw new RuntimeException(x);
    }
    return String.valueOf(Hex.encodeHex(utf8));
}

/**
* Decodes the given string by using the hexadecimal representation of its UTF-8 bytes.
*
* @param s The string to decode.
* @return The decoded string.
* @throws Exception If an error occurs.
*/
public static String utf8HexDecode(String s) throws Exception {
if (s == null) {
    return null;
}
    return new String(Hex.decodeHex(s.toCharArray()), ENCODING_UTF8);
} 

更新: 感谢drawnonward在这里的答案,这是我编写用于创建十六进制NSString的方法。在char声明行上,它会给我一个“Initialization discards qualifiers from pointer target type”的警告,但它仍然可以工作。

- (NSString *)stringToHex:(NSString *)string
{
    char *utf8 = [string UTF8String];
    NSMutableString *hex = [NSMutableString string];
    while ( *utf8 ) [hex appendFormat:@"%02X" , *utf8++ & 0x00FF];

    return [NSString stringWithFormat:@"%@", hex];
}

我还没有时间编写解码方法。当我有时间时,我会编辑此内容并将其发布给其他感兴趣的人。

更新2:所以我上面发布的方法实际上并没有输出我要找的内容。它不是以0-f格式输出十六进制值,而是输出了所有数字。我最终回到了这个问题并且编写了一个NSString分类,完全复制了我之前发布的Java方法。这是代码:

//
//  NSString+hex.h
//  Created by Ben Baron on 10/20/10.
//

@interface NSString (hex) 

    + (NSString *) stringFromHex:(NSString *)str;
    + (NSString *) stringToHex:(NSString *)str;

@end

//
//  NSString+hex.m
//  Created by Ben Baron on 10/20/10.
//

#import "NSString+hex.h"

@implementation NSString (hex)

+ (NSString *) stringFromHex:(NSString *)str 
{   
    NSMutableData *stringData = [[[NSMutableData alloc] init] autorelease];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    int i;
    for (i=0; i < [str length] / 2; i++) {
        byte_chars[0] = [str characterAtIndex:i*2];
        byte_chars[1] = [str characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [stringData appendBytes:&whole_byte length:1]; 
    }

    return [[[NSString alloc] initWithData:stringData encoding:NSASCIIStringEncoding] autorelease];
}

+ (NSString *) stringToHex:(NSString *)str
{   
    NSUInteger len = [str length];
    unichar *chars = malloc(len * sizeof(unichar));
    [str getCharacters:chars];

    NSMutableString *hexString = [[NSMutableString alloc] init];

    for(NSUInteger i = 0; i < len; i++ )
    {
        [hexString appendString:[NSString stringWithFormat:@"%x", chars[i]]];
    }
    free(chars);

    return [hexString autorelease];
}

@end

我有这段代码在家里。除非有人比我更快地发布它,否则我下班后会把它发布出来。 - Jon Shier
嗨,我知道这是一个旧帖子。但我遇到了你面临的问题,而且是的。你对于 stringFromHex 方法的发现正是我也在寻找的。请问您从哪里得到这个方法,是否有教程可以参考?我想理解这个方法,但我自己无法分析它。谢谢。 - Melvin Lai
抱歉,时间太久了,我已经记不起来了。 - Ben Baron
方法stringToHex:仍然只输出数字:( - pash3r
8个回答

29

将NSString转换为十六进制值的完美简短方法

NSMutableString *tempHex=[[NSMutableString alloc] init];

[tempHex appendString:@"0xD2D2D2"];

unsigned colorInt = 0;

[[NSScanner scannerWithString:tempHex] scanHexInt:&colorInt];

lblAttString.backgroundColor=UIColorFromRGB(colorInt);

用于这段代码的宏是----

#define UIColorFromRGB(rgbValue) 
[UIColor \colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

1
也许您可以在回答中附上您的UIColorFromRGB宏实现。 - Jasper Blues
嗨@JasperBlues,我已经更新了我的帖子,并添加了所需的宏。 - Prasanna

23

对于这些Java代码:

utf8 = s.getBytes(ENCODING_UTF8);
new String(decodedHexString, ENCODING_UTF8);

对应于Objective-C的等价物是

utf8 = [s UTF8String];
[NSString initWithUTF8String:decodedHexString];

将一个字符串的十六进制表示转换为NSString:

NSMutableString *hex = [NSMutableString string];
while ( *utf8 ) [hex appendFormat:@"%02X" , *utf8++ & 0x00FF];

你需要自己编写一个decodeHex函数。从字符串中提取两个字符,如果它们有效,则将一个字节添加到结果中。


2
应该是 "NSMutableString *hex = [NSMutableString string];" - Berik
我喜欢这个“while循环”一行代码的答案。请注意NULL字节。如果您尝试abc。然后检查结果是否与以下内容匹配:https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA256.pdf 。此代码会在十六进制编码哈希末尾遇到NULL字节时出现错误。 - rustyMagnet

11

你的stringToHex方法有一个问题 - 它会删除前导0,并忽略00。作为一种快速修复,我编写了以下代码:

+ (NSString *) stringToHex:(NSString *)str
{   
    NSUInteger len = [str length];
    unichar *chars = malloc(len * sizeof(unichar));
    [str getCharacters:chars];

    NSMutableString *hexString = [[NSMutableString alloc] init];

    for(NSUInteger i = 0; i < len; i++ )
    {
        // [hexString [NSString stringWithFormat:@"%02x", chars[i]]]; /*previous input*/
        [hexString appendFormat:@"%02x", chars[i]]; /*EDITED PER COMMENT BELOW*/
    }
    free(chars);

    return [hexString autorelease];
}

我没有意识到这一点。可能会导致我不知道存在的随机罕见错误。谢谢! - Ben Baron
3
你的代码中有一个小bug,[hexString [NSString stringWithFormat:@"%02x", chars[i]]]; 应该改为 [hexString appendString:[NSString stringWithFormat:@"%02x", chars[i]]]; 或者更好的写法是 [hexString appendFormat:@"%02x", chars[i]]; - Ben Baron
我还没有编辑权限,所以我无法使用修复方法编辑你的答案。 - Ben Baron

9

感谢所有在这个帖子中做出贡献的人。对我来说,这是一个巨大的帮助。由于自原帖发布以来事情有所发展,现在我更新了iOS 6的实现。我采用了类别方法,但选择将负载分配给NSData和NSString。欢迎评论。

首先是NSString部分,它处理将十六进制编码的字符串解码为NSData对象。

@implementation NSString (StringToHexData)

//
// Decodes an NSString containing hex encoded bytes into an NSData object
//
- (NSData *) stringToHexData
{
    int len = [self length] / 2;    // Target length
    unsigned char *buf = malloc(len)
    unsigned char *whole_byte = buf;
    char byte_chars[3] = {'\0','\0','\0'};

    int i;
    for (i=0; i < [self length] / 2; i++) {
        byte_chars[0] = [self characterAtIndex:i*2];
        byte_chars[1] = [self characterAtIndex:i*2+1];
        *whole_byte = strtol(byte_chars, NULL, 16);
        whole_byte++;
    }

    NSData *data = [NSData dataWithBytes:buf length:len];
    free( buf );
    return data;
}
@end

这些改变主要是为了提高效率:一些简单的老式指针算法意味着我可以一次性分配整个缓冲区,并逐字节填充它。然后整个东西一次性传递给NSData。

在NSData中,编码部分看起来像这样:

@implementation NSData (DataToHexString)

- (NSString *) dataToHexString
{
    NSUInteger          len = [self length];
    char *              chars = (char *)[self bytes];
    NSMutableString *   hexString = [[NSMutableString alloc] init];

    for(NSUInteger i = 0; i < len; i++ )
        [hexString appendString:[NSString stringWithFormat:@"%0.2hhx", chars[i]]];

    return hexString;
}
@end

再次进行了一些微小的更改,但我怀疑这里没有任何效率提升。使用“%0.2hhx”解决了所有前导零丢失的问题,并确保每次仅输出一个字节。

希望这能帮助下一个处理此事的人!


3
一个可能的解决方案:
+(NSString*)hexFromStr:(NSString*)str
{
    NSData* nsData = [str dataUsingEncoding:NSUTF8StringEncoding];
    const char* data = [nsData bytes];
    NSUInteger len = nsData.length;
    NSMutableString* hex = [NSMutableString string];
    for(int i = 0; i < len; ++i)[hex appendFormat:@"%02X", data[i]];
    return hex;
}

这里不适合使用 const - Ray Shih

1

首先,我想感谢drawnonward的回答。这为我提供了第一个函数mean和clean。在同样的精神下,我写了另一个函数。希望你喜欢。

@synthesize unsigned char* value= _value;

- (NSString*) hexString
{
    _value[CONSTANT]= '\0';
    unsigned char* ptr= _value;

    NSMutableString* hex = [[NSMutableString alloc] init];
    while ( *ptr ) [hex appendFormat:@"%02x", *ptr++ & 0x00FF];

    return [hex autorelease];
}

- (void) setHexString:(NSString*)hexString
{
    _value[CONSTANT]= '\0';
    unsigned char* ptr= _value;

    for (const char* src= [hexString cStringUsingEncoding:NSASCIIStringEncoding];
         *src;
         src+=2)
    {
        unsigned int hexByte;
        /*int res=*/ sscanf(src,"%02x",&hexByte);
        *ptr++= (unsigned char)(hexByte & 0x00FF);
    }
    *ptr= '\0';
}

0

我的输入是一个十进制字符串,输出应该是字符串格式的十六进制表示。例如:

  • @"10" -> @"A"
  • @"1128" -> @"468"
  • @"1833828235" -> @"6D4DFF8B"

实现:

+ (NSString *) stringToHex:(NSString *)str{
NSInteger result = [str integerValue];
NSString *hexStr = (result)?@"":@"0";

while (result!=0) {
     NSInteger reminder = result % 16;

    if(reminder>=0 && reminder<=9){
        hexStr = [[NSString stringWithFormat:@"%ld",(long)reminder] stringByAppendingString:hexStr];
    }else if(reminder==10){
        hexStr = [@"A" stringByAppendingString:hexStr];
    }else if(reminder==11){
        hexStr = [@"B" stringByAppendingString:hexStr];
    }else if(reminder==12){
        hexStr = [@"C" stringByAppendingString:hexStr];
    }else if(reminder==13){
        hexStr = [@"D" stringByAppendingString:hexStr];
    }else if(reminder==14){
        hexStr = [@"E" stringByAppendingString:hexStr];
    }else{
        hexStr = [@"F" stringByAppendingString:hexStr];
    }

    result /=16;
}

return hexStr;

}


-1
也许你应该使用NSStringdataUsingEncoding:方法进行编码,并使用initWithData:length:encoding:方法进行解码。具体取决于你从哪里获取数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接