Это категория, применяемая к написанным мной NSData. Он возвращает шестнадцатеричное NSString, представляющее NSData, где данные могут быть любой длины. Возвращает пустую строку, если NSData пусто.
NSData + Conversion.h
#import <Foundation/Foundation.h>
@interface NSData (NSData_Conversion)
#pragma mark - String Conversion
- (NSString *)hexadecimalString;
@end
NSData + Conversion.m
#import "NSData+Conversion.h"
@implementation NSData (NSData_Conversion)
#pragma mark - String Conversion
- (NSString *)hexadecimalString {
/* Returns hexadecimal string of NSData. Empty string if data is empty. */
const unsigned char *dataBuffer = (const unsigned char *)[self bytes];
if (!dataBuffer)
return [NSString string];
NSUInteger dataLength = [self length];
NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (int i = 0; i < dataLength; ++i)
[hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];
return [NSString stringWithString:hexString];
}
@end
Использование:
NSData *someData = ...;
NSString *someDataHexadecimalString = [someData hexadecimalString];
Это «вероятно» лучше, чем вызов [someData description]
с последующим удалением пробелов, <и>. Удаление персонажей кажется слишком "хакерским". Кроме того, вы никогда не знаете, изменит ли Apple форматирование NSData -description
в будущем.
ПРИМЕЧАНИЕ. Люди обращались ко мне по поводу лицензирования кода в этом ответе. Настоящим я посвящаю свои авторские права на код, опубликованный в этом ответе, в общественное достояние.
"%02lx"
с этим приведением, или приведен к(unsigned int)
, или отброшен и использован@"%02hhx"
:)[hexString appendFormat:@"%02x", (unsigned int)dataBuffer[i]];
намного лучше (меньший объем памяти)Вот высоко оптимизированный метод категории NSData для генерации шестнадцатеричной строки. Хотя ответа @Dave Gallagher достаточно для относительно небольшого размера, производительность памяти и процессора ухудшается для больших объемов данных. Я профилировал это с помощью файла размером 2 МБ на своем iPhone 5. Сравнение времени было 0,05 против 12 секунд. Объем памяти при использовании этого метода незначителен, в то время как другой метод увеличил размер кучи до 70 МБ!
источник
Использование свойства описания NSData не следует рассматривать как приемлемый механизм для HEX-кодирования строки. Это свойство предназначено только для описания и может быть изменено в любое время. Обратите внимание, что до iOS свойство description NSData даже не возвращало данные в шестнадцатеричной форме.
Извините за то, что настаивал на решении, но важно потратить силы на его сериализацию без использования API, который предназначен для чего-то другого, кроме сериализации данных.
источник
description
возвращает строку в шестнадцатеричной кодировке, поэтому мне это кажется разумным.Вот более быстрый способ выполнить преобразование:
BenchMark (среднее время для преобразования данных размером 1024 байта, повторенного 100 раз):
Дэйв Галлахер: ~ 8,070 мс
Программист NSP: ~ 0,077 мс
Питер: ~ 0,031 мс
Этот: ~ 0,017 мс
источник
_hexString
метод): github.com/ZipArchive/ZipArchive/blob/master/SSZipArchive/…Функциональная версия Swift
Один лайнер:
Вот форма многоразового самодокументируемого расширения:
В качестве альтернативы, используйте
reduce("", combine: +)
вместо того,joinWithSeparator("")
чтобы вас видели в качестве функционального мастера.Изменить: я изменил String ($ 0, radix: 16) на String (format: "% 02x", $ 0), потому что для однозначных чисел необходимо иметь нулевое заполнение
источник
Ответ Питера перенесен на Swift
swift3
Swift 5
источник
Мне нужно было решить эту проблему, и я нашел здесь очень полезные ответы, но я беспокоюсь о производительности. Большинство этих ответов связаны с массовым копированием данных из NSData, поэтому я написал следующее, чтобы выполнить преобразование с низкими накладными расходами:
Это предварительно выделяет пространство в строке для всего результата и позволяет избежать копирования содержимого NSData с помощью enumerateByteRangesUsingBlock. При замене X на x в строке формата будут использоваться шестнадцатеричные цифры нижнего регистра. Если вам не нужен разделитель между байтами, вы можете уменьшить оператор
до всего
источник
NSRange
указывает диапазон в пределах большегоNSData
представления, а не в пределах меньшего буфера байтов (этот первый параметр блока, предоставленногоenumerateByteRangesUsingBlock
), который представляет единственную непрерывную часть большегоNSData
. Таким образом,byteRange.length
отражает размер буфера байтов, ноbyteRange.location
это место в пределах большегоNSData
. Таким образом, вы хотите использовать простоoffset
, а неbyteRange.location + offset
извлекать байт.appendFormat
вам, вероятно, также следует изменить егоself.length * 3
наself.length * 2
Мне нужен был ответ, который работал бы со строками переменной длины, поэтому вот что я сделал:
Прекрасно работает как расширение для класса NSString.
источник
Вы всегда можете использовать [yourString uppercaseString] для использования заглавных букв в описании данных.
источник
Лучший способ сериализации / десериализации NSData в NSString - использовать кодировщик / декодер Base64 Google Toolbox для Mac . Просто перетащите в свой проект приложения файлы GTMBase64.m, GTMBase64.he GTMDefines.h из пакета Foundation и выполните что-то вроде
источник
string = [data base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]
Вот решение с использованием Swift 3
источник
источник
Измените
%08x
на,%08X
чтобы получить заглавные символы.источник
Swift + Property.
Я предпочитаю иметь шестнадцатеричное представление как свойство (так же, как
bytes
иdescription
свойства):Идея заимствована из этого ответа
источник
Вам нужно будет удалить пробелы.
Лично я
base64
кодируюdeviceToken
, но это дело вкуса.источник