ios fileExistsAtPath 新文件失败
Posted
技术标签:
【中文标题】ios fileExistsAtPath 新文件失败【英文标题】:ios fileExistsAtPath failing for new file 【发布时间】:2012-10-10 21:59:47 【问题描述】:我正在编写一个文件,然后将 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 偶尔会失败。大概这是因为有时在断言运行时文件还没有完全写入和解锁? (对于大文件?)
我应该如何解决这个问题?
【问题讨论】:
好吧,断言设置为确保 fileExists 如此推测该文件不存在并且失败(可能是因为没有完全写入,尽管我不确定)。 assert 用于调试目的,您真正应该关心的是为什么在创建之前在该路径上调用addSkipBackupAttributeToItemAtURL:
。还要检查您设置的路径是否有效。
【参考方案1】:
解决此问题的最简单方法可能是将NO
用于writeToFile:atomically:
方法的atomically:
参数。
NO
将使系统将文件直接写入其最终目标/路径(而不是使用临时文件然后移动它)。
所以我的猜测是,当使用atomically:YES
并因此使用临时文件时,当您调用addSkipBackupAttributeToItemAtURL:
时,系统可能还没有完成临时文件的写入(因此甚至没有开始移动它到它的最终路径/目的地),它解释了你的断言失败的原因。
虽然使用atomically:NO
,但当您调用addSkipBackupAttributeToItemAtURL:
时,系统至少已经开始写入最终路径,并且您的断言应该不会失败。
【讨论】:
【参考方案2】:根据writeToFile:atomically:
上的文档:
原子地
如果是,则将数据写入备份文件,然后——假设没有发生错误——备份文件被重命名为路径指定的名称;否则,数据直接写入路径。
只是一个假设,但是当您调用 [data writeToFile:filePath atomically:YES];
时,您的调用可能会在临时文件完成写入但尚未发生重命名时返回,在这种情况下 [[NSFileManager defaultManager] fileExistsAtPath: [URL path]]
将返回 NO。
我的预感是,如果您将呼叫切换到 [data writeToFile:filePath atomically:NO]
,这个错误就会消失。
【讨论】:
【参考方案3】:随后的调查显示 writeToFile 是同步的,并且在方法返回时文件将被写入。
该问题是由于遇到包含斜杠字符“/”的自动生成文件名引起的。这意味着文件创建失败。我现在已经将 writeToFile;atomically 更改为:
BOOL bWorked = [data writeToFile:filePath options:NSDataWritingAtomic error:&errorPtr];
if (!bWorked)
NSLog(@"writeDataToFileWithData failed for %@ %@", filePath,errorPtr);
【讨论】:
以上是关于ios fileExistsAtPath 新文件失败的主要内容,如果未能解决你的问题,请参考以下文章
fileExistsAtPath判断是否有文件一直返回NO的bug
当路径正确时,为啥 NSFIleManager -fileExistsAtPath 找不到现有文件?
无法将文件从包复制到 Documents 目录,为啥 fileExistsAtPath 返回错误?
无法通过 fileExistsAtPath 在文件夹中找到我下载的文件
fileExistsAtPath 和 checkResourceIsReachableAndReturnError 都不起作用