当我调用-description
一个NSData
对象时,我看到一个NSData
对象字节的十六进制字符串,如:
<f6e7cd28 0fc5b5d4 88f8394b af216506 bc1bba86 4d5b483d>
Run Code Online (Sandbox Code Playgroud)
我希望将数据的这种表示(减去lt/gt引号)放入内存中,NSString
这样我就可以使用它.我不想调用-[NSData description]
然后只修剪lt/gt引号(因为我认为这不是NSData
公共界面的保证方面,并且将来会发生变化.
将NSData
对象表示为NSString
对象(除了调用之外-description
)的最简单方法是什么?
Eri*_*ner 81
请记住,任何String(format: ...)
解决方案都会非常慢(对于大数据)
NSData *data = ...;
NSUInteger capacity = data.length * 2;
NSMutableString *sbuf = [NSMutableString stringWithCapacity:capacity];
const unsigned char *buf = data.bytes;
NSInteger i;
for (i=0; i<data.length; ++i) {
[sbuf appendFormat:@"%02X", (NSUInteger)buf[i]];
}
Run Code Online (Sandbox Code Playgroud)
如果你需要更高性能的东西试试这个:
static inline char itoh(int i) {
if (i > 9) return 'A' + (i - 10);
return '0' + i;
}
NSString * NSDataToHex(NSData *data) {
NSUInteger i, len;
unsigned char *buf, *bytes;
len = data.length;
bytes = (unsigned char*)data.bytes;
buf = malloc(len*2);
for (i=0; i<len; i++) {
buf[i*2] = itoh((bytes[i] >> 4) & 0xF);
buf[i*2+1] = itoh(bytes[i] & 0xF);
}
return [[NSString alloc] initWithBytesNoCopy:buf
length:len*2
encoding:NSASCIIStringEncoding
freeWhenDone:YES];
}
Run Code Online (Sandbox Code Playgroud)
Swift 4.2版本
extension Data {
var hexString: String? {
return withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in
let charA = UInt8(UnicodeScalar("a").value)
let char0 = UInt8(UnicodeScalar("0").value)
func itoh(_ value: UInt8) -> UInt8 {
return (value > 9) ? (charA + value - 10) : (char0 + value)
}
let hexLen = count * 2
let ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: hexLen)
for i in 0 ..< count {
ptr[i*2] = itoh((bytes[i] >> 4) & 0xF)
ptr[i*2+1] = itoh(bytes[i] & 0xF)
}
return String(bytesNoCopy: ptr,
length: hexLen,
encoding: .utf8,
freeWhenDone: true)
}
}
}
Run Code Online (Sandbox Code Playgroud)
Ali*_*are 29
我同意解决方案不要调用description
哪个是保留用于调试,所以好点和好问题:)
最简单的解决方案是循环遍历字节NSData
并从中构造NSString.使用[yourData bytes]
访问字节,并建立串入一个NSMutableString
.
以下是使用NSData类别实现此示例的示例
@interface NSData(Hex)
-(NSString*)hexRepresentationWithSpaces_AS:(BOOL)spaces;
@end
@implementation NSData(Hex)
-(NSString*)hexRepresentationWithSpaces_AS:(BOOL)spaces
{
const unsigned char* bytes = (const unsigned char*)[self bytes];
NSUInteger nbBytes = [self length];
//If spaces is true, insert a space every this many input bytes (twice this many output characters).
static const NSUInteger spaceEveryThisManyBytes = 4UL;
//If spaces is true, insert a line-break instead of a space every this many spaces.
static const NSUInteger lineBreakEveryThisManySpaces = 4UL;
const NSUInteger lineBreakEveryThisManyBytes = spaceEveryThisManyBytes * lineBreakEveryThisManySpaces;
NSUInteger strLen = 2*nbBytes + (spaces ? nbBytes/spaceEveryThisManyBytes : 0);
NSMutableString* hex = [[NSMutableString alloc] initWithCapacity:strLen];
for(NSUInteger i=0; i<nbBytes; ) {
[hex appendFormat:@"%02X", bytes[i]];
//We need to increment here so that the every-n-bytes computations are right.
++i;
if (spaces) {
if (i % lineBreakEveryThisManyBytes == 0) [hex appendString:@"\n"];
else if (i % spaceEveryThisManyBytes == 0) [hex appendString:@" "];
}
}
return [hex autorelease];
}
@end
Run Code Online (Sandbox Code Playgroud)
用法:
NSData* data = ...
NSString* hex = [data hexRepresentationWithSpaces_AS:YES];
Run Code Online (Sandbox Code Playgroud)
Joh*_*und 22
只是想补充说@ PassKits的方法可以使用Swift 3非常优雅地编写,因为Data
现在是一个集合.
extension Data {
var hex: String {
var hexString = ""
for byte in self {
hexString += String(format: "%02X", byte)
}
return hexString
}
}
Run Code Online (Sandbox Code Playgroud)
要么 ...
extension Data {
var hex: String {
return self.map { b in String(format: "%02X", b) }.joined()
}
}
Run Code Online (Sandbox Code Playgroud)
甚至 ...
extension Data {
var hex: String {
return self.reduce("") { string, byte in
string + String(format: "%02X", byte)
}
}
}
Run Code Online (Sandbox Code Playgroud)
ma1*_*w28 20
我最喜欢@ Erik_Aigner的答案.我只是重构了一下:
NSData *data = [NSMutableData dataWithBytes:"acani" length:5];
NSUInteger dataLength = [data length];
NSMutableString *string = [NSMutableString stringWithCapacity:dataLength*2];
const unsigned char *dataBytes = [data bytes];
for (NSInteger idx = 0; idx < dataLength; ++idx) {
[string appendFormat:@"%02x", dataBytes[idx]];
}
Run Code Online (Sandbox Code Playgroud)
在Swift中,您可以创建扩展.
extension NSData {
func toHexString() -> String {
var hexString: String = ""
let dataBytes = UnsafePointer<CUnsignedChar>(self.bytes)
for (var i: Int=0; i<self.length; ++i) {
hexString += String(format: "%02X", dataBytes[i])
}
return hexString
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以简单地使用:
let keyData: NSData = NSData(bytes: [0x00, 0xFF], length: 2)
let hexString = keyData.toHexString()
println("\(hexString)") // Outputs 00FF
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
43371 次 |
最近记录: |