我遇到在iOS设备(iPad)中写入大文件(> 200 MB)的问题,但在模拟器中它完美无缺。
我使用NSFileManager
创建文件,使用NSFileData
来编写文件。
我认为我的代码没有问题,因为它在模拟器中运行良好。
有没有人有同样的问题?
详细说明我的情况:
我正在保存我的设备中的大块文件(每个3MB)。这意味着对于一个300 MB的文件,我有100个块。现在,从100个块我想创建实际文件。所以我在第一次迭代中使用NSFileManager
创建文件,然后使用NSFileData
在文件末尾写入3MB数据。在运行程序时,它会在61个块之后崩溃。我猜测iPad中可能存在一些与内存相关的问题。
我正在以fileDir
格式保存文件块,格式为data-0,data-1,data-2 ......
我正在对数据应用解密操作,但为了简单起见,我删除了该部分。
// List of chunk files
NSArray *filelist= [[NSFileManager defaultManager] contentsOfDirectoryAtPath:fileDir error:err];
for(int i = 0; i < [filelist count]; i++) {
// Read the chunk of file
fileName = [[NSString alloc] initWithFormat:@"data-%d", i];
filePath = [fileDir stringByAppendingPathComponent:fileName];
fileReadHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
// Write in tempFile
if(offset == 0){
if([[NSFileManager defaultManager] createFileAtPath:tempFile contents:data attributes:nil]){
fileWriteHandle = [NSFileHandle fileHandleForWritingAtPath:tempFile];
NSLog(@"File was created!");
} else {
NSLog(@"File was not created.");
}
} else {
[fileWriteHandle seekToEndOfFile]; // Tried with comment out this line but same problem
// Write the decrypted data from chunk
[fileWriteHandle writeData:[[fileReadHandle readDataToEndOfFile] decryptedAES256DataUsingKey:AESEncryptionKey error:err]];
}
}
编辑(2013年2月11日) 我尝试使用之前的代码,省略了数据解密部分。 有趣的是,问题是在解密部分,我猜没有解密它导致它工作正常。我已经添加了解密代码。对于解密,我使用的是NSData + CommonCrypto库(它不是ARC),但我的项目是在ARC中。
答案 0 :(得分:2)
这可能是操作系统问题,因为NSFileHandle永远不会为每个块关闭。我建议关闭它。
此外,看起来你的变量是在for循环范围之外声明的。除非你需要在循环外部使用这些变量,否则保持变量范围尽可能小是很好的,特别是如果你使用ARC并且正在考虑何时释放内存。
如果您认为NSFileHandle持有内存中的数据,请在编写每个块后尝试使用-synchronizeFile
方法,以确保内存更改反映到磁盘上。
另外,我将你正在编写的文件的创建移到了循环之外,因为它对我来说更容易理解。
尝试此调整:
// List of chunk files
NSArray *filelist= [[NSFileManager defaultManager] contentsOfDirectoryAtPath:fileDir error:err];
if([[NSFileManager defaultManager] createFileAtPath:tempFile contents:[NSData data] attributes:nil]){
NSLog(@"File was created!");
} else {
NSLog(@"File was not created.");
}
NSFileHandle *fileWriteHandle = [NSFileHandle fileHandleForWritingAtPath:tempFile];
for(int i = 0; i < [filelist count]; i++) {
// Read the chunk of file
NSString *fileName = [NSString stringWithFormat:@"data-%d", i];
NSString *filePath = [fileDir stringByAppendingPathComponent:fileName];
NSFileHandle *fileReadHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
NSData *data = [fileReadHandle readDataToEndOfFile];
// No longer using the file
[fileReadHandle closeFile];
// Write in tempFile
[fileWriteHandle writeData:data];
[fileWriteHandle synchronizeFile];// Flush any data in memory to disk
}
[fileWriteHandle closeFile];
答案 1 :(得分:0)
修改以下代码就像魔术一样,
@autoreleasepool {
[fileWriteHandle writeData:[[fileReadHandle readDataToEndOfFile] decryptedAES256DataUsingKey:AESEncryptionKey error:err]];
}