Esta é uma categoria aplicada a NSData que escrevi. Ele retorna um NSString hexadecimal que representa o NSData, onde os dados podem ter qualquer comprimento. Retorna uma string vazia se NSData estiver vazio.
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
Uso:
NSData *someData = ...;
NSString *someDataHexadecimalString = [someData hexadecimalString];
Isso é "provavelmente" melhor do que chamar [someData description]
e remover os espaços, <'s e>' s. Despir personagens parece muito "hacky". Além disso, você nunca sabe se a Apple mudará a formatação dos NSData -description
no futuro.
NOTA: algumas pessoas me procuraram sobre o licenciamento do código desta resposta. Eu, por meio deste, dedico meus direitos autorais do código que postei nesta resposta ao domínio público.
"%02lx"
com esse elenco, ou elenco para(unsigned int)
, ou elimine o elenco e use@"%02hhx"
:)[hexString appendFormat:@"%02x", (unsigned int)dataBuffer[i]];
é muito melhor (pegada de memória menor)Aqui está um método de categoria NSData altamente otimizado para gerar uma string hexadecimal. Embora a resposta de @Dave Gallagher seja suficiente para um tamanho relativamente pequeno, o desempenho da memória e da CPU se deteriora para grandes quantidades de dados. Fiz o perfil disso com um arquivo de 2 MB no meu iPhone 5. A comparação de tempo foi de 0,05 contra 12 segundos. O consumo de memória é insignificante com este método, enquanto o outro método aumentou o heap para 70 MBs!
fonte
Usar a propriedade de descrição de NSData não deve ser considerado um mecanismo aceitável para codificação HEX da string. Essa propriedade é apenas para descrição e pode ser alterada a qualquer momento. Como uma observação, pré-iOS, a propriedade de descrição NSData nem mesmo retornava seus dados em formato hexadecimal.
Desculpe por insistir na solução, mas é importante aproveitar a energia para serializá-la sem pegar carona em uma API que se destina a algo diferente da serialização de dados.
fonte
description
retorna uma string codificada em hexadecimal, o que me parece razoável.Esta é uma maneira mais rápida de fazer a conversão:
BenchMark (tempo médio para uma conversão de dados de 1024 bytes repetida 100 vezes):
Dave Gallagher: ~
8,070 ms NSProgrammer: ~ 0,077 ms
Peter: ~ 0,031 ms
Este aqui: ~ 0,017 ms
fonte
_hexString
método): github.com/ZipArchive/ZipArchive/blob/master/SSZipArchive/…Versão funcional do Swift
Um liner:
Este é um formulário de extensão reutilizável e autodocumentável:
Alternativamente, use em
reduce("", combine: +)
vez dejoinWithSeparator("")
ser visto como um mestre funcional por seus colegas.Edit: Eu mudei String ($ 0, radix: 16) para String (formato: "% 02x", $ 0), porque números de um dígito precisavam ter um zero de preenchimento
fonte
A resposta de Peter portada para Swift
swift3
Swift 5
fonte
Eu precisava resolver esse problema e achei as respostas aqui muito úteis, mas me preocupo com o desempenho. A maioria dessas respostas envolve a cópia de dados em massa de NSData, então escrevi o seguinte para fazer a conversão com baixa sobrecarga:
Isso pré-aloca espaço na string para todo o resultado e evita a cópia do conteúdo NSData usando enumerateByteRangesUsingBlock. Alterar o X para um x na string de formato usará dígitos hexadecimais minúsculos. Se você não quiser um separador entre os bytes, você pode reduzir a instrução
para baixo para apenas
fonte
NSRange
indica o intervalo dentro daNSData
representação maior , não dentro do buffer de bytes menores (aquele primeiro parâmetro do bloco fornecido paraenumerateByteRangesUsingBlock
) que representa uma única parte contígua do maiorNSData
. Assim,byteRange.length
reflete o tamanho do buffer de bytes, masbyteRange.location
é a localização dentro do maiorNSData
. Portanto, você deseja usar simplesmenteoffset
, nãobyteRange.location + offset
, para recuperar o byte.appendFormat
, provavelmente também deve alterar oself.length * 3
paraself.length * 2
Eu precisava de uma resposta que funcionasse com strings de comprimento variável, então aqui está o que fiz:
Funciona muito bem como uma extensão para a classe NSString.
fonte
Você sempre pode usar [yourString uppercaseString] para colocar letras maiúsculas na descrição dos dados
fonte
A melhor maneira de serializar / desserializar NSData em NSString é usar o codificador / decodificador Google Toolbox para Mac Base64. Basta arrastar para o seu projeto de aplicativo os arquivos GTMBase64.m, GTMBase64.he GTMDefines.h do pacote Foundation e fazer algo como
fonte
string = [data base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]
Aqui está uma solução usando Swift 3
fonte
fonte
Mude
%08x
para%08X
para obter caracteres maiúsculos.fonte
Propriedade Swift +.
Eu prefiro ter uma representação hexadecimal como propriedade (o mesmo que
bytes
edescription
propriedades):A ideia é emprestada desta resposta
fonte
Você precisará remover os espaços.
Pessoalmente,
base64
codifico odeviceToken
, mas é uma questão de gosto.fonte