如何在 Objective-C 中对 NSData 进行按位异或?
Posted
技术标签:
【中文标题】如何在 Objective-C 中对 NSData 进行按位异或?【英文标题】:How do I do a bit-wise XOR on NSData in Objective-C? 【发布时间】:2015-04-28 01:45:20 【问题描述】:我有两个 NSData 对象 data1 和 data2,我想做一个按位异或并将结果存储在第三个 NSData 对象 xorData 中。
我尝试的第一件事是:
*data1.bytes^*data2.bytes;
但它给出了一个错误:
二进制表达式的无效操作数('const void' 和 'const void')
所以我尝试编写一个函数,将数据的字节提取到整数数组中,对整数执行异或,然后将结果保存回 NSData 对象。函数如下所示:
+(NSData *) DataXOR1:(NSData *) data1
DataXOR2:(NSData *)data2
const int *data1Bytes = [data1 bytes];
const int *data2Bytes = [data2 bytes];
NSMutableArray *xorBytes = [[NSMutableArray alloc] init ];
for (int i = 0; i < data1.length;i++)
[xorBytes addObject:[NSNumber numberWithInt:(data1Bytes[i]^data2Bytes[i])]];
NSData *xorData = [NSKeyedArchiver archivedDataWithRootObject:xorBytes];
return xorData;
这运行,但给出了错误的答案。当我在两个简单的数据(data1 = 0x7038 和 data2 = 0x0038)上测试它并使用 NSLog 输出值是什么时,我得到:
data1Bytes[0] = 8070450532247943280
data2Bytes[0] = 8070450532247943168
data1Bytes[0]^data2Bytes[0] = 112
data1Bytes[1] = 10376302331560798334
data2Bytes[1] = 10376302331560798334
data1Bytes[1]^data2Bytes[1] = 0
这让我有点不知所措,因为 dataXBytes 数组中的值完全错误,但它们与正确的值异或! (0x70 ^ 0x00 = 0x70 = 112)
我认为这可能是字节序问题,但是当我将 data1Bytes 的初始化更改为:
const int *data1Bytes = CFSwapInt32BigToHost([data1 bytes]);
它在尝试访问它时遇到错误,说:
线程 1:EXC_BAD_ACCESS(code=1, address = 0xa08ad539)
有没有更简单的方法来做异或?如果没有,我该如何解决字节序问题?
【问题讨论】:
如果您从 NSData 对象中获取字节数组,为什么将它们声明为int
数组? (这只是你的问题之一。)
仅供参考,8070450532247943280
= 0x7000000000003870
。和8070450532247943168
= 0x7000000000003800
。所以 xor 对我来说看起来不错。正如 Hot Licks 所暗示的,问题在于您正在使用 int *
指针并获得 64 位数字。底层数据是什么?您是否有理由不使用更能代表字节的东西(例如uint8_t
)?你到底想做什么?您没有向我们展示 NSData
对象中的内容,因此我们很难提供建议。
【参考方案1】:
投射到int
然后归档NSNumber
s 的NSArray
肯定不会产生您正在寻找的结果。你会想要一些可变的NSData
来附加各个字节,比如
+(NSData *) DataXOR1:(NSData *) data1
DataXOR2:(NSData *)data2
const char *data1Bytes = [data1 bytes];
const char *data2Bytes = [data2 bytes];
// Mutable data that individual xor'd bytes will be added to
NSMutableData *xorData = [[NSMutableData alloc] init];
for (int i = 0; i < data1.length; i++)
const char xorByte = data1Bytes[i] ^ data2Bytes[i];
[xorData appendBytes:&xorByte length:1];
return xorData;
【讨论】:
谢谢,这完美!不过,如果您不介意回答两个问题: 1) 为什么 char 是指向通用数据字节的最佳选择? 2)据我了解,循环在每次迭代中初始化变量“xorByte”,以便它将在内存中为数据分配一个点,然后“appendBytes:&xorByte”使 xorData 指向所有这些新变量。对吗? (1)char
保证实际上是一个字节,而 int
不是。 (2) xorByte
是一个堆栈变量,它在每个循环中进出堆栈内存(尽管可能有一个优化使它的寿命更长),对-appendBytes:length:
的调用实际上是副本 i> 将xorByte
的值转化为xorData
的内部数据。【参考方案2】:
+ (NSData *) xorData:(NSData *)data1 with:(NSData *)data2
// make data1 smaller
if (data1.length > data2.length)
NSData *t = data1;
data1 = data2;
data2 = t;
char *xor = (char *) malloc(data2.length * sizeof(char));
char * data1Bytes = (char *) data1.bytes;
char * data2Bytes = (char *) data2.bytes;
for (int i = 0; i <data1.length; i++)
xor[i] = data1Bytes[i] ^ data2Bytes[i];
NSMutableData *data = [[[NSMutableData alloc] initWithBytes:xor length:data1.length] autorelease];
[data appendData:[data2 subdataWithRange:NSMakeRange(data1.length, data2.length - data1.length)]];
free(xor);
return [NSData dataWithData:data];
【讨论】:
1.不要转换malloc
的结果。 2. 首先为什么要使用malloc?请改用NSMutableData
并避免复制。 3. 不要再进行不必要的复制(在最后一行)。
我想返回 NSData,而不是 NSMutableData,那么最好的方法是什么?
返回(非可变)NSData
有什么意义?该实例是在您的本地源代码中创建的,而不是共享或存储的。方法返回后不能对其进行变异。调用者无法区分可变实例和非可变副本。
最佳实践。 “方法返回后不能变异。” > 你确定吗?我不这么认为。如果转换为 NSMutableData,则返回值可能会发生变化,因为原始指针是可变对象。
没错,调用者可以做到这一点。但这将是调用者的(错误)决定。调用者当然不应该这样做,因为这意味着依赖 xor 方法的实现细节。 xor 方法不应该担心外部代码可能会滥用其返回值。以上是关于如何在 Objective-C 中对 NSData 进行按位异或?的主要内容,如果未能解决你的问题,请参考以下文章
Objective-C NSData/NSMutableData
将 NSData Objective-C 代码转换为 Swift 时遇到问题