2015-04-28 1 views
1

У меня есть два объекта NSData, data1 и data2, и я хотел бы сделать бит-мудрый XOR и сохранить результат в третьем объекте NSData, xorData.Как сделать бит XOR по NSData в Objective-C?

Первое, что я попытался было это:

*data1.bytes^*data2.bytes; 

но это дало ошибку:

инвалидных операндов бинарного выражения ('Const ничтожной' и 'Const пустоты')

Итак, я попытался написать функцию, которая будет извлекать байты данных в массив целых чисел, выполнять xor для целых чисел, а затем сохранить результат обратно в 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 (код = 1, адрес = 0xa08ad539)

есть ли более простой способ сделать XOR? Если нет, как я могу исправить проблему с endian?

+0

Если вы получаете массивы байтов из объектов NSData, почему вы объявляете им быть 'ИНТ 'массивы ??? (И это только одна из ваших проблем.) –

+0

FYI, '8070450532247943280' =' 0x7000000000003870'. И '8070450532247943168' =' 0x7000000000003800'. Так что xor выглядит хорошо для меня. Проблема, как говорит Hot Licks, заключается в том, что вы используете указатели 'int *' и получаете 64-битные номера. Каковы основные данные? Есть ли причина, по которой вы не используете что-то более представительное из байта (например, 'uint8_t')? Что именно вы пытаетесь сделать? Вы не показываете нам, что находится в объектах 'NSData', поэтому нам сложно предложить адвоката. – Rob

ответ

2

Отливка от int, тогда архивирование NSArray от NSNumber s не обязательно создаст ожидаемый результат. Вы хотите иметь некоторые изменяемые 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; 
} 
+0

Спасибо, это работает отлично! Если вы не возражаете ответить на два вопроса об этом: 1) Почему char является лучшим выбором для указания на общий байт данных? 2) Как я понимаю, цикл инициализирует переменную «xorByte» на каждой итерации, чтобы выделить место в памяти для данных, а затем «appendBytes: & xorByte» приводит к тому, что xorData указывает на все эти новые переменные. Это правильно? –

+0

(1) 'char' гарантированно будет фактически одним байтом, тогда как' int' - нет. (2) 'xorByte' - это переменная стека, которая входит в стек и выходит из стековой памяти в каждом цикле (хотя может быть оптимизация, которая делает ее более долговечной), вызов' -appendBytes: length: 'на самом деле * копий * значение 'xorByte' в внутренние данные' xorData'. –

1
+ (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]; 
} 
+0

1. Не выдавайте результат 'malloc'. 2. Почему malloc в первую очередь? Вместо этого используйте «NSMutableData» и избегайте копирования. 3. Не выполняйте лишнюю копию (в последней строке). –

+0

Я хотел бы вернуть NSData, а не NSMutableData, тогда что лучше всего? – karim

+0

Какой смысл возвращать (не изменяемые) 'NSData'? Экземпляр создается в вашем локальном исходном коде, а не является общим или сохраненным. Он не может быть мутирован после возвращения метода. Вызывающий не может определить разницу между изменяемым экземпляром и не изменяемой копией. –

Смежные вопросы