在ios设备中无法写入大文件(> 200MB,在我的情况下为700MB)?

时间:2013-02-10 05:47:15

标签: ios objective-c ios5

我遇到在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中。

2 个答案:

答案 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]]; 
}