Как преобразовать NSString в шестнадцатеричные значения - PullRequest
28 голосов
/ 17 июня 2010

Я хотел бы преобразовать обычную строку NSString в строку NSString с (что я предполагаю) шестнадцатеричными значениями ASCII и обратно.

Мне нужно выдать тот же вывод, что и методы 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);
} 

Обновление: Благодаря ответу drawonward, вот метод, который я написал для создания шестнадцатеричных строк NSS.Он выдает мне предупреждение «Инициализация сбрасывает квалификаторы из целевого типа указателя» в строке объявления символа, но это работает.

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

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

У нас еще не было времени написать метод декодирования.Когда я это сделаю, я отредактирую это, чтобы опубликовать его для всех, кто интересуется.

Update2: Таким образом, метод, который я разместил выше, фактически не выводит то, что я ищу.Вместо вывода шестнадцатеричных значений в формате 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

Ответы [ 8 ]

28 голосов
/ 17 июня 2013

Идеальный и короткий способ преобразования 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]
22 голосов
/ 17 июня 2010

Для этих строк Java

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

эквивалентами Objective-C будет

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

Чтобы создать строку NSS с шестнадцатеричным представлением строки символов:

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

Вы должны будете сделать свою собственную функцию decodeHex. Просто извлеките два символа из строки и, если они действительны, добавьте в результат байт.

8 голосов
/ 22 февраля 2012

Существует проблема с вашим методом 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];
}
6 голосов
/ 10 января 2013

Спасибо всем, кто внес вклад в эту тему.Это была большая помощь для меня.Поскольку после первоначального поста дела пошли немного дальше, вот моя обновленная реализация для 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 голосов
/ 12 августа 2013

Одно из возможных решений:

+(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;
}
1 голос
/ 08 декабря 2011

Итак, во-первых, я хотел бы поблагодарить 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';
}
0 голосов
/ 12 декабря 2016

Мой ввод был строкой base10, а вывод должен быть шестнадцатеричным представлением в строковом формате.Примеры:

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

}

0 голосов
/ 17 июня 2010

Возможно, вам следует использовать NSString dataUsingEncoding: для кодирования и initWithData:length:encoding: для декодирования.Зависит от того, откуда вы получаете данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...