Как преобразовать значения NSString в шестнадцатеричные значения
Я хотел бы преобразовать обычный NSString в NSString с (что я предполагаю) шестнадцатеричными значениями ASCII и обратно.
Мне нужно создать тот же результат, что и методы Java ниже, но я не могу найти способ сделать это в Objective-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);
}
Обновление: Благодаря обратному ответу здесь метод, который я написал для создания шестнадцатеричных NSStrings. Это дает мне предупреждение "Отказ от инициализации отключений от типа указателя" в строке объявления char, но он работает.
- (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
Ответы
Ответ 1
Для этих строк 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
Идеальный и короткий способ преобразования 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
Возникает проблема с вашим методом stringToHex - он пропускает ведущие 0 и игнорирует 00s. Как быстро, я сделал следующее:
+ (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
Спасибо всем, кто внес свой вклад в эту тему. Это очень помогло мне. Так как ситуация немного изменилась со времени первоначального сообщения, здесь моя обновленная версия для 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" разрешило все проблемы отсутствия нулевого ведущего нуля и гарантирует, что одновременно выводится только один байт.
Надеюсь, это поможет следующему человеку принять это!
Ответ 5
Одно из возможных решений:
+(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
Итак, во-первых, я хотел бы поблагодарить 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
Моим входом была строка с цифрой base10, а результат должен быть шестнадцатеричным представлением в строковом формате. Примеры:
- @ "10" → @ "A"
- @ "1128" → @ "468"
- @ "1833828235" → @ "6D4DFF8B"
Реализация:
+ (NSString *) stringToHex:(NSString *)str{
NSInteger result = [str integerValue];
NSString *hexStr = (result)[email protected]"":@"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
Возможно, вы должны использовать NSString
dataUsingEncoding:
для кодирования и initWithData:length:encoding:
для декодирования. Зависит от того, откуда вы получаете данные.