在iOS上使用RNCryptorasynchronous解密大文件
我需要iOS上的RNCryptorasynchronous解密大文件(以显示进度条)。 我没有发现任何地方的例子,因此已经尝试了我所猜测的是正确的,但是…我得到的东西不起作用:解密程序的处理程序不会被调用,并且线程在发送所有数据后与EXC_BAD_ADDRESS一起崩溃在函数的结尾。
NSOutputStream *decryptedStream = [NSOutputStream outputStreamToFileAtPath:decryptedPath append:NO]; [decryptedStream open]; NSUInteger totalBytesToRead = [[[NSFileManager defaultManager] attributesOfItemAtPath:tempPath error:nil] fileSize]; __block NSUInteger totalBytesRead = 0; LOG("I've got %d bytes to decrypt.", totalBytesToRead); RNDecryptor *decryptor = [[RNDecryptor alloc] initWithPassword:SNCatalogPassword handler:^(RNCryptor *cryptor, NSData *data) { totalBytesRead += data.length; [decryptedStream write:data.bytes maxLength:data.length]; LOG("Decrypted %d bytes : %d / %d bytes treated", data.length, totalBytesRead, totalBytesToRead); if (cryptor.isFinished) { //proceed LOG("Done with decrypting."); [decryptedStream close]; } }]; // Feed data to the decryptor NSInputStream *cryptedStream = [NSInputStream inputStreamWithFileAtPath:tempPath]; [cryptedStream open]; while (cryptedStream.hasBytesAvailable) { uint8_t buf[4096]; NSUInteger bytesRead = [cryptedStream read:buf maxLength:4096]; NSData *data = [NSData dataWithBytes:buf length:bytesRead]; LOG("Sending %d bytes to decryptor...", bytesRead); dispatch_async(dispatch_get_main_queue(), ^{ [decryptor addData:data]; }); } LOG("Sent everything."); [decryptor finish]; [cryptedStream close];
(比较而言, tempPath
是encryption文件的path; tempPath
是解密数据应写入的path)。
另外我是ARC新手,所以这可能是一个内存或调度相关的问题。
谢谢你的帮助。
我今天遇到了同样的问题,这似乎是由于在iOS6中最近弃用dispatch_get_current_queue()而发生的。
通过更改[RNCryptor initWithHandler:]创build一个新的队列,解密工作正常。
NSString *responseQueueName = [@"net.robnapier.response." stringByAppendingString:NSStringFromClass([self class])]; _responseQueue = dispatch_queue_create([responseQueueName UTF8String], NULL);
你可以在github的fork上的async_decrypt分支上find修复和相关的unit testing(根据你的代码)。
提交 csteynberg / RNCryptor
你的行为是由于asynchronous执行:在调用addData之前调用[decryptor finish] :要解决这个问题,你应该replace
while (cryptedStream.hasBytesAvailable) { //...
通过
while (YES) { if (!cryptedStream.hasBytesAvailable) { dispatch_async(dispatch_get_main_queue(), ^{ [decryptor finish]; }); break; } //...
(当然,除去现有的调用[解密完成] )这种方式完成后总是调用所有的数据发送。
问候