0

我在 iOS 设备 (iPad) 中写入大文件 (>200 MB) 时遇到问题,但在模拟器中它运行良好。
我正在使用NSFileManager创建文件和NSFileData写入文件。我认为我的代码没有问题,因为它在模拟器中运行良好。有没有人有同样的问题?

详细说明我的情况:

我在我的设备中保存了大量文件(每个 3MB),效果很好。这意味着对于 300 MB 的文件,我有 100 个块。现在,我想从 100 个块中创建实际文件。所以我NSFileManager在第一次迭代中使用创建文件,然后使用NSFileData在文件末尾写入 3MB 数据。在运行程序时,它在 61 个块后崩溃。我猜 iPad 中可能存在一些与内存相关的问题。

我正在以fileDirdata-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]];
                    }
                }

编辑(11.02.2013) 我尝试使用我以前的代码,其中我省略了数据解密部分。有趣的是,问题出在解密部分,我猜是因为没有解密它可以正常工作。我已经添加了解密代码。对于解密,我使用的是 NSData+CommonCrypto 库(它不是 ARC),但我的项目在 ARC 中。

4

2 回答 2

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];
于 2013-02-10T22:45:01.980 回答
1

修改以下代码就像魔术一样,

@autoreleasepool { 
[fileWriteHandle writeData:[[fileReadHandle readDataToEndOfFile] decryptedAES256DataUsingKey:AESEncryptionKey error:err]]; 
}
于 2013-02-11T10:24:40.473 回答