代码之家  ›  专栏  ›  技术社区  ›  Ben Baron

如何将nsstring转换为十六进制值

  •  28
  • Ben Baron  · 技术社区  · 14 年前

    我想将一个普通的nsstring转换成一个nsstring,并返回(我假设是)ascii十六进制值。

    我需要产生与下面的Java方法相同的输出,但是在Objy-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);
    } 
    

    更新: 感谢Drawnwood的回答,这里是我编写的创建十六进制nsstring的方法。它在char声明行上给出了“初始化丢弃指针目标类型的限定符”警告,但它起作用。

    - (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格式输出十六进制值,而是输出所有数字。我终于回到了这个问题上,并且能够为NScript编写一个类别,它完全复制了我发布的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
    
    8 回复  |  直到 8 年前
        1
  •  22
  •   Alex Terente    12 年前

    对于Java的这些行

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

    目标C当量为

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

    要使用字符串的十六进制表示形式生成nsstring,请执行以下操作:

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

    你必须自己做decodehex函数。只需从字符串中拉出两个字符,如果它们有效,则向结果中添加一个字节。

        2
  •  28
  •   Prasanna PeyloW    11 年前

    将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]
    
        3
  •  8
  •   Michael Dautermann    13 年前

    你的stringtohex方法有一个问题-它删除了前导0,忽略了0。作为一个快速修复,我做了如下:

    + (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];
    }
    
        4
  •  6
  •   smee    12 年前

    感谢所有在这方面做出贡献的人。这对我很有帮助。自从最初发布以来,事情有了一些进展,下面是我为iOS6更新的实现。我使用Categories方法,但选择在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”解决了丢失前导零的所有问题,并确保一次只输出一个字节。

    希望这能帮助下一个接受这个的人!

        5
  •  3
  •   HotJard    11 年前

    一种可能的解决方案:

    +(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;
    }
    
        6
  •  1
  •   Community CDub    7 年前

    所以,首先,我想感谢 drawnonward 为了他的回答。这给了我第一个功能,卑鄙和干净。本着同样的精神,我写了另一篇。希望你喜欢。

    @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';
    }
    
        7
  •  0
  •   Javier Calatrava Llavería    8 年前

    我的输入是一个以数字为基础的10字符串,输出应该是字符串格式的十六进制表示。实例:

    • @“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;
    

    }

        8
  •  -1
  •   falconcreek    14 年前

    也许你应该用 NSString dataUsingEncoding: 编码和 initWithData:length:encoding: 解码。取决于从何处获取数据。