objective-c - 将 NSData 转换为十六进制 NSString

标签 objective-c cocoa hex nsdata nsscanner

引用以下问题:Convert NSData into HEX NSString

我已经使用 Erik Aigner 提供的解决方案解决了这个问题:

NSData *data = ...;
NSUInteger capacity = [data length] * 2;
NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:capacity];
const unsigned char *dataBuffer = [data bytes];
NSInteger i;
for (i=0; i<[data length]; ++i) {
  [stringBuffer appendFormat:@"%02X", (NSUInteger)dataBuffer[i]];
}

但是有个小问题,如果后面多了个零,字符串值就会不一样。例如。如果十六进制数据是字符串@"3700000000000000",当使用扫描仪转换为整数时:

unsigned result = 0;
NSScanner *scanner = [NSScanner scannerWithString:stringBuffer];
[scanner scanHexInt:&result];
NSLog(@"INTEGER: %u",result);

结果将是 4294967295,这是不正确的。不应该是 55,因为只取了 hexa 37 吗?

那么如何去掉零呢?

编辑:(响应 CRD)

您好,感谢您澄清我的疑惑。那么您正在做的是直接从字节指针实际读取 64 位整数,对吗?但是我还有一个问题。您实际上如何将 NSData 转换为字节指针?

为了让您更容易理解,我将解释一下我最初所做的事情。

首先,我显示了我拥有的文件的数据(数据是十六进制的)

NSData *file = [NSData dataWithContentsOfFile:@"file path here"];
NSLog(@"Patch File: %@",file);

输出:

enter image description here

接下来,我读取并偏移文件的前 8 个字节,并将它们转换为字符串。

// 0-8 bytes
[file seekToFileOffset:0];
NSData *b = [file readDataOfLength:8];
NSUInteger capacity = [b length] * 2;
NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:capacity];
const unsigned char *dataBuffer = [b bytes];
NSInteger i;
for (i=0; i<[b length]; ++i) {
    [stringBuffer appendFormat:@"%02X", (NSUInteger)dataBuffer[i]];
}
NSLog(@"0-8 bytes HEXADECIMAL: %@",stringBuffer);

如您所见,0x3700000000000000 是接下来的 8 个字节。要访问接下来的 8 个字节,我必须做的唯一更改是将 SeekFileToOffset 的值更改为 8,以便访问接下来的 8 个字节的数据。

总而言之,您给我的解决方案很有用,但是手动输入十六进制值是不切实际的。如果将字节格式化为字符串然后解析它们不是这样做的方法,那么如何直接访问数据的前 8 个字节并将它们转换为字节指针?

最佳答案

您似乎在尝试将存储在 NSData 中的 8 个字节转换为 64 位整数(0x3700000000000000 中有 8 个字节)。

如果这是您的目标,那么通过将字节格式化为字符串然后解析它们来实现它是不是的方法。您需要找出您的数据采用的endian 格式(即最低或最高有效字节优先),然后使用适当的字节序转换函数。

顺便说一句,你得到 4294967295 (0xFFFFFFFF) 的原因是因为你要求 NSScanner 读取一个 32 位整数,而你的数字 (0x3700000000000000) 溢出。

回复评论

由于 x86 是小端字节序的,您可以通过强制转换直接从字节指针读取一个小端字节序的 64 位整数:

Byte bytes[] = { 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
NSLog(@"%lld", *(int64_t *)bytes);

如果您需要读取 big-endian 数据,那么您可以使用诸如 Endian64_Swap 之类的字节序转换函数 - 它只会翻转您拥有的数据,因此先读取再翻转。

请注意,x86 不要求数据访问对齐,但如果对齐,性能会更好。

关于objective-c - 将 NSData 转换为十六进制 NSString,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13489349/

相关文章:

cocoa - NSBrowser 填充 NSPasteboard 但不会掉落

vb.net - 将字符串发送到其等效的十六进制值

objective-c - 如何使用 Swift 和 Objective-C 创建 XML 文件?

ios - 使用多维数组创建 @property

objective-c - NSLocking 的使用是否应该始终包含在@try/@finally 中?

cocoa - 如何处理 NSTextField 中的文本选择

iphone - 在启动动画之前修改 iPhone 动画容器 View

ios - AFURLSessionManager downloadTaskWithRequest 立即取消

ios - 十六进制 - 什么编码?

c++ - 为什么 C++ 在使用 std::hex 而不是大写时打印小写字母表?