Iphone 将NSData序列化为十六进制字符串的最佳方法
我正在寻找一种将NSData对象序列化为十六进制字符串的好方法。其想法是在将其发送到我的服务器之前序列化用于通知的deviceToken 我有以下实现,但我认为必须有一些更短更好的方法来实现它Iphone 将NSData序列化为十六进制字符串的最佳方法,iphone,notifications,nsdata,Iphone,Notifications,Nsdata,我正在寻找一种将NSData对象序列化为十六进制字符串的好方法。其想法是在将其发送到我的服务器之前序列化用于通知的deviceToken 我有以下实现,但我认为必须有一些更短更好的方法来实现它 + (NSString*) serializeDeviceToken:(NSData*) deviceToken { NSMutableString *str = [NSMutableString stringWithCapacity:64]; int length = [deviceTo
+ (NSString*) serializeDeviceToken:(NSData*) deviceToken
{
NSMutableString *str = [NSMutableString stringWithCapacity:64];
int length = [deviceToken length];
char *bytes = malloc(sizeof(char) * length);
[deviceToken getBytes:bytes length:length];
for (int i = 0; i < length; i++)
{
[str appendFormat:@"%02.2hhX", bytes[i]];
}
free(bytes);
return str;
}
+(NSString*)序列化deviceToken:(NSData*)deviceToken
{
NSMutableString*str=[NSMutableString stringWithCapacity:64];
整数长度=[deviceToken长度];
char*bytes=malloc(sizeof(char)*长度);
[deviceToken getBytes:字节长度:长度];
for(int i=0;i
您需要删除空格
我个人
base64
对deviceToken
进行编码,但这是一个品味问题。将%08x
更改为%08x
,以获得大写字符。我需要一个适用于可变长度字符串的答案,因此我做了以下工作:
+ (NSString *)stringWithHexFromData:(NSData *)data
{
NSString *result = [[data description] stringByReplacingOccurrencesOfString:@" " withString:@""];
result = [result substringWithRange:NSMakeRange(1, [result length] - 2)];
return result;
}
非常适合作为NSString类的扩展。您可以始终使用[yourString uppercaseString]将数据描述中的字母大写。将NSData序列化/反序列化为NSString的更好方法是使用Base64编码器/解码器。只需拖动到你的应用程序项目中,文件GTMBase64.m,GTMBase64.H.GTM.从包基础上定义H。
/**
* Serialize NSData to Base64 encoded NSString
*/
-(void) serialize:(NSData*)data {
self.encodedData = [GTMBase64 stringByEncodingData:data];
}
/**
* Deserialize Base64 NSString to NSData
*/
-(NSData*) deserialize {
return [GTMBase64 decodeString:self.encodedData];
}
使用NSData的description属性不应被视为对字符串进行十六进制编码的可接受机制。该属性仅用于描述,可以随时更改。值得注意的是,在iOS之前,NSData description属性甚至没有以十六进制形式返回其数据 很抱歉重复这个解决方案,但重要的是要花精力对其进行序列化,而不必借助于用于数据序列化以外的其他用途的API
@implementation NSData (Hex)
- (NSString*)hexString
{
NSUInteger length = self.length;
unichar* hexChars = (unichar*)malloc(sizeof(unichar) * (length*2));
unsigned char* bytes = (unsigned char*)self.bytes;
for (NSUInteger i = 0; i < length; i++) {
unichar c = bytes[i] / 16;
if (c < 10) {
c += '0';
} else {
c += 'A' - 10;
}
hexChars[i*2] = c;
c = bytes[i] % 16;
if (c < 10) {
c += '0';
} else {
c += 'A' - 10;
}
hexChars[i*2+1] = c;
}
NSString* retVal = [[NSString alloc] initWithCharactersNoCopy:hexChars length:length*2 freeWhenDone:YES];
return [retVal autorelease];
}
@end
实施NSData(十六进制)
-(NSString*)十六进制字符串
{
NSU整数长度=self.length;
unichar*hexChars=(unichar*)malloc(sizeof(unichar)*(长度*2));
无符号字符*字节=(无符号字符*)self.bytes;
对于(整数i=0;i#import <Foundation/Foundation.h>
@interface NSData (NSData_Conversion)
#pragma mark - String Conversion
- (NSString *)hexadecimalString;
@end
这“可能”比调用[someData description]
然后剥离空格,@implementation NSData(Extn)要好
-(NSString*)说明
{
NSMutableString*str=[[NSMutableString alloc]init];
const char*bytes=self.bytes;
对于(int i=0;i<[自身长度];i++){
[格式:@“%02hhX”,字节[i]];
}
返回[str自动释放];
}
@结束
现在可以调用NSLog(@“十六进制值:%@”,data)
我需要解决这个问题,发现这里的答案非常有用,但我担心性能。大多数答案都涉及从NSData中批量复制数据,因此我编写了以下内容,以低开销进行转换:
@interface NSData (HexString)
@end
@implementation NSData (HexString)
- (NSString *)hexString {
NSMutableString *string = [NSMutableString stringWithCapacity:self.length * 3];
[self enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop){
for (NSUInteger offset = 0; offset < byteRange.length; ++offset) {
uint8_t byte = ((const uint8_t *)bytes)[offset];
if (string.length == 0)
[string appendFormat:@"%02X", byte];
else
[string appendFormat:@" %02X", byte];
}
}];
return string;
}
直截了当
[string appendFormat:@"%02X", byte];
这里有一个生成十六进制字符串的高度优化的方法。虽然@Dave Gallagher的答案对于相对较小的大小来说已经足够了,但对于大量数据,内存和cpu性能会恶化。我在iphone5上用一个2MB的文件分析了这个问题。时间比较为0.05 vs 12秒。此方法的内存占用可以忽略不计,而另一种方法将堆增加到70MBs
- (NSString *) hexString
{
NSUInteger bytesCount = self.length;
if (bytesCount) {
const char *hexChars = "0123456789ABCDEF";
const unsigned char *dataBuffer = self.bytes;
char *chars = malloc(sizeof(char) * (bytesCount * 2 + 1));
if (chars == NULL) {
// malloc returns null if attempting to allocate more memory than the system can provide. Thanks Cœur
[NSException raise:NSInternalInconsistencyException format:@"Failed to allocate more memory" arguments:nil];
return nil;
}
char *s = chars;
for (unsigned i = 0; i < bytesCount; ++i) {
*s++ = hexChars[((*dataBuffer & 0xF0) >> 4)];
*s++ = hexChars[(*dataBuffer & 0x0F)];
dataBuffer++;
}
*s = '\0';
NSString *hexString = [NSString stringWithUTF8String:chars];
free(chars);
return hexString;
}
return @"";
}
-(NSString*)十六进制字符串
{
NSUTEGER字节数=self.length;
if(字节计数){
常量字符*hexChars=“0123456789ABCDEF”;
const unsigned char*dataBuffer=self.bytes;
char*chars=malloc(sizeof(char)*(字节数*2+1));
if(chars==NULL){
//如果试图分配系统无法提供的内存,malloc将返回null。谢谢Cœur
[NSException raise:NSInternalInconsistencyException格式:@“分配更多内存失败”参数:nil];
返回零;
}
char*s=chars;
for(无符号i=0;i>4];
*s++=hexChars[(*dataBuffer&0x0F)];
dataBuffer++;
}
*s='\0';
NSString*hexString=[NSString stringWithUTF8String:chars];
免费(chars);
返回十六进制字符串;
}
返回@”;
}
彼得的回答传给了斯威夫特
func hexString(data:NSData)->String{
if data.length > 0 {
let hexChars = Array("0123456789abcdef".utf8) as [UInt8];
let buf = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes), count: data.length);
var output = [UInt8](count: data.length*2 + 1, repeatedValue: 0);
var ix:Int = 0;
for b in buf {
let hi = Int((b & 0xf0) >> 4);
let low = Int(b & 0x0f);
output[ix++] = hexChars[ hi];
output[ix++] = hexChars[low];
}
let result = String.fromCString(UnsafePointer(output))!;
return result;
}
return "";
}
以下是进行转换的更快方法: 基准测试(1024字节数据转换重复100次的平均时间): 戴夫·加拉赫:~8.070毫秒
NSProgrammer:~0.077毫秒
彼得:~0.031毫秒
这个:~0.017毫秒
@implementation NSData (BytesExtras)
static char _NSData_BytesConversionString_[512] = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
-(NSString*)bytesString
{
UInt16* mapping = (UInt16*)_NSData_BytesConversionString_;
register UInt16 len = self.length;
char* hexChars = (char*)malloc( sizeof(char) * (len*2) );
// --- Coeur's contribution - a safe way to check the allocation
if (hexChars == NULL) {
// we directly raise an exception instead of using NSAssert to make sure assertion is not disabled as this is irrecoverable
[NSException raise:@"NSInternalInconsistencyException" format:@"failed malloc" arguments:nil];
return nil;
}
// ---
register UInt16* dst = ((UInt16*)hexChars) + len-1;
register unsigned char* src = (unsigned char*)self.bytes + len-1;
while (len--) *dst-- = mapping[*src--];
NSString* retVal = [[NSString alloc] initWithBytesNoCopy:hexChars length:self.length*2 encoding:NSASCIIStringEncoding freeWhenDone:YES];
#if (!__has_feature(objc_arc))
return [retVal autorelease];
#else
return retVal;
#endif
}
@end
功能性Swift版本
一艘班轮:
let hexString = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes),
count: data.length).map { String(format: "%02x", $0) }.joinWithSeparator("")
let hexString=UnsafeBufferPointer(开始:UnsafePointer(data.bytes),
count:data.length).map{String(格式:'%02x',$0)}.joinWithSeparator(“”)
以下是一个可重用且自文档化的扩展表单:
extension NSData {
func base16EncodedString(uppercase uppercase: Bool = false) -> String {
let buffer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(self.bytes),
count: self.length)
let hexFormat = uppercase ? "X" : "x"
let formatString = "%02\(hexFormat)"
let bytesAsHexStrings = buffer.map {
String(format: formatString, $0)
}
return bytesAsHexStrings.joinWithSeparator("")
}
}
扩展数据{
func base16EncodedString(大写:Bool=false)->字符串{
let buffer=UnsafeBufferPointer(开始:UnsafePointer(self.bytes)),
计数:自我长度)
设hexFormat=大写?“X”:“X”
let formatString=“%02\(hexFormat)”
让bytesAsHexStrings=buffer.map{
s
- (NSString *) hexString
{
NSUInteger bytesCount = self.length;
if (bytesCount) {
const char *hexChars = "0123456789ABCDEF";
const unsigned char *dataBuffer = self.bytes;
char *chars = malloc(sizeof(char) * (bytesCount * 2 + 1));
if (chars == NULL) {
// malloc returns null if attempting to allocate more memory than the system can provide. Thanks Cœur
[NSException raise:NSInternalInconsistencyException format:@"Failed to allocate more memory" arguments:nil];
return nil;
}
char *s = chars;
for (unsigned i = 0; i < bytesCount; ++i) {
*s++ = hexChars[((*dataBuffer & 0xF0) >> 4)];
*s++ = hexChars[(*dataBuffer & 0x0F)];
dataBuffer++;
}
*s = '\0';
NSString *hexString = [NSString stringWithUTF8String:chars];
free(chars);
return hexString;
}
return @"";
}
func hexString(data:NSData)->String{
if data.length > 0 {
let hexChars = Array("0123456789abcdef".utf8) as [UInt8];
let buf = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes), count: data.length);
var output = [UInt8](count: data.length*2 + 1, repeatedValue: 0);
var ix:Int = 0;
for b in buf {
let hi = Int((b & 0xf0) >> 4);
let low = Int(b & 0x0f);
output[ix++] = hexChars[ hi];
output[ix++] = hexChars[low];
}
let result = String.fromCString(UnsafePointer(output))!;
return result;
}
return "";
}
func hexString()->String{
if count > 0 {
let hexChars = Array("0123456789abcdef".utf8) as [UInt8];
return withUnsafeBytes({ (bytes:UnsafePointer<UInt8>) -> String in
let buf = UnsafeBufferPointer<UInt8>(start: bytes, count: self.count);
var output = [UInt8](repeating: 0, count: self.count*2 + 1);
var ix:Int = 0;
for b in buf {
let hi = Int((b & 0xf0) >> 4);
let low = Int(b & 0x0f);
output[ix] = hexChars[ hi];
ix += 1;
output[ix] = hexChars[low];
ix += 1;
}
return String(cString: UnsafePointer(output));
})
}
return "";
}
func hexString()->String{
if count > 0 {
let hexChars = Array("0123456789abcdef".utf8) as [UInt8];
return withUnsafeBytes{ bytes->String in
var output = [UInt8](repeating: 0, count: bytes.count*2 + 1);
var ix:Int = 0;
for b in bytes {
let hi = Int((b & 0xf0) >> 4);
let low = Int(b & 0x0f);
output[ix] = hexChars[ hi];
ix += 1;
output[ix] = hexChars[low];
ix += 1;
}
return String(cString: UnsafePointer(output));
}
}
return "";
}
@implementation NSData (BytesExtras)
static char _NSData_BytesConversionString_[512] = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
-(NSString*)bytesString
{
UInt16* mapping = (UInt16*)_NSData_BytesConversionString_;
register UInt16 len = self.length;
char* hexChars = (char*)malloc( sizeof(char) * (len*2) );
// --- Coeur's contribution - a safe way to check the allocation
if (hexChars == NULL) {
// we directly raise an exception instead of using NSAssert to make sure assertion is not disabled as this is irrecoverable
[NSException raise:@"NSInternalInconsistencyException" format:@"failed malloc" arguments:nil];
return nil;
}
// ---
register UInt16* dst = ((UInt16*)hexChars) + len-1;
register unsigned char* src = (unsigned char*)self.bytes + len-1;
while (len--) *dst-- = mapping[*src--];
NSString* retVal = [[NSString alloc] initWithBytesNoCopy:hexChars length:self.length*2 encoding:NSASCIIStringEncoding freeWhenDone:YES];
#if (!__has_feature(objc_arc))
return [retVal autorelease];
#else
return retVal;
#endif
}
@end
let hexString = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes),
count: data.length).map { String(format: "%02x", $0) }.joinWithSeparator("")
extension NSData {
func base16EncodedString(uppercase uppercase: Bool = false) -> String {
let buffer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(self.bytes),
count: self.length)
let hexFormat = uppercase ? "X" : "x"
let formatString = "%02\(hexFormat)"
let bytesAsHexStrings = buffer.map {
String(format: formatString, $0)
}
return bytesAsHexStrings.joinWithSeparator("")
}
}
extension NSData {
var hexString: String {
let buffer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(self.bytes), count: self.length)
return buffer.map { String(format: "%02x", $0) }.joinWithSeparator("")
}
var heXString: String {
let buffer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(self.bytes), count: self.length)
return buffer.map { String(format: "%02X", $0) }.joinWithSeparator("")
}
}
extension Data {
public var hexadecimalString : String {
var str = ""
enumerateBytes { buffer, index, stop in
for byte in buffer {
str.append(String(format:"%02x",byte))
}
}
return str
}
}
extension NSData {
public var hexadecimalString : String {
return (self as Data).hexadecimalString
}
}