0

我正在编写一个文件,然后将 NSURLIsExcludedFromBackupKey 属性添加到文件中。为此,我的 HPSFileHelper 类中有以下两种方法:

+(void)writeDataToFileWithData:(NSData*)data andFilename:(NSString*)fileName
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 

    NSString *documentsDirectory = [paths objectAtIndex:0]; 

    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];

    [data writeToFile:filePath atomically:YES];

    NSURL* fileURL = [NSURL fileURLWithPath:filePath];

    [HPSFileHelper addSkipBackupAttributeToItemAtURL:fileURL]; // Prevent this file from being backed up.
}

+(BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
    assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);

    NSError *error = nil;
    BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
                                  forKey: NSURLIsExcludedFromBackupKey error: &error];
    if(!success){
        NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
    }
    return success;

}

问题是 assert ... fileExistsAtPath 偶尔会失败。大概这是因为有时在断言运行时文件还没有完全写入和解锁?(对于大文件?)

我应该如何围绕这个问题编写代码?

4

3 回答 3

1

解决此问题的最简单方法可能是使用方法NOatomically:参数writeToFile:atomically:

  • 以原子方式写入文件 意味着系统将文件内容写入临时文件中,一旦全部写入,将文件移动到最终路径。 (这是为了确保在写入文件失败的情况下,例如,最终路径不包含未完成的文件内容)
  • 使用NO此参数将使系统将文件直接写入其最终目标/路径(而不是使用临时文件然后移动它)。

所以我的猜测是,当使用atomically:YES并因此使用临时文件时,当您调用addSkipBackupAttributeToItemAtURL:系统时,可能还没有完成临时文件的写入(因此甚至没有开始将其移动到最终路径/目标)并且它解释了为什么您的断言失败。

而使用atomically:NO,当您调用时,系统至少已经开始写入最终路径,addSkipBackupAttributeToItemAtURL:并且您的断言应该不会失败。

于 2012-10-10T22:49:02.410 回答
1

根据以下文档writeToFile:atomically:

原子地

如果是,则将数据写入备份文件,然后——假设没有发生错误——备份文件被重命名为路径指定的名称;否则,数据直接写入路径。

只是一个假设,但是当您调用 时[data writeToFile:filePath atomically:YES];,您的调用可能会在临时文件完成写入但尚未发生重命名时返回,在这种情况下[[NSFileManager defaultManager] fileExistsAtPath: [URL path]]将返回 NO。

我的预感是,如果您将呼叫切换到[data writeToFile:filePath atomically:NO],这个错误就会消失。

于 2012-10-10T22:52:42.640 回答
0

随后的调查显示 writeToFile 是同步的,并且文件将在方法返回时被写入。

该问题是由遇到包含斜杠字符“/”的自动生成文件名引起的。这意味着文件创建失败。我现在已将 writeToFile; 原子地更改为:

BOOL bWorked = [data writeToFile:filePath options:NSDataWritingAtomic error:&errorPtr];

if (!bWorked)
{
    NSLog(@"writeDataToFileWithData failed for %@ %@", filePath,errorPtr);
}
于 2012-10-11T08:02:33.800 回答