如何在Cocoa中安全地移动/交换文件?

如何在Cocoa中安全地移动/交换文件?,cocoa,macos,nsfilemanager,Cocoa,Macos,Nsfilemanager,在我的cocoa应用程序中,有一种方法对sqlite数据库的模式执行一些可能具有破坏性的操作,因此首先我们制作数据库的回滚副本,如果出现错误,我们调用以下方法以回滚文件替换db文件。请注意,我绝对希望用回滚替换db文件 - (BOOL)restoreDatabaseFromFileAtPath:(NSString *)backupPath error:(NSError **)error { NSFileManager *fm = [NSFileManager defaultManager

在我的cocoa应用程序中,有一种方法对sqlite数据库的模式执行一些可能具有破坏性的操作,因此首先我们制作数据库的回滚副本,如果出现错误,我们调用以下方法以回滚文件替换db文件。请注意,我绝对希望用回滚替换db文件

- (BOOL)restoreDatabaseFromFileAtPath:(NSString *)backupPath error:(NSError **)error {
    NSFileManager *fm = [NSFileManager defaultManager];
    // get the db paths
    NSString *databasePath = [sharedManager pathToDatabase];

    // insist that the two files be present
    NSAssert1([fm fileExistsAtPath:databasePath], @"no db file at %@", databasePath);
    NSAssert1([fm fileExistsAtPath:backupPath], @"no backup db file at %@", backupPath);

    // remove the original to make way for the backup
    NSLog(@"removing the file at the primary database path...");
    if ([fm removeItemAtPath:databasePath error:error]) {
        // now move the backup to the original location
        NSLog(@"moving the backup file into the primary database path...");
        if ([fm moveItemAtPath:backupPath toPath:databasePath error:error]) {
            return YES;
        }
    }
    [self presentError:error]; // at this point we're in real trouble
    return NO;
}
显示的代码确实有效,但它可能具有非常大的破坏性,而且不完全是原子性的。我真正想做的是我想象中存在的事情,但我无法在NSFileManager的API中找到这样做的方法,比如:

Bool success = [fm moveFileAtPath:backupPath toPath:databasePath overwriteDestination:YESPLZ error:&error];
当发现目标路径上已经有一个文件时,与此最接近的方法会发出barfs

根据到目前为止的回复进行小更新:


Cocoa开发人员必须采用某种传统的标准方法,以原子方式替换文件。NSFileManager的各种“移动”方法都没有提供现成的工具。此外,希望在此库中支持10.5及以上版本以及iPhone OS 3+。

C级/功能可能会有所帮助。这些函数采用一组选项,其中可以包括,
kFSFileOperationOverwrite
,等等。

关于
NSFileManager
replaceItemAttribute:WithItemAttribute:backupItemName:options:resultingItemURL:error:


我建议使用
fsExchangeObject
pbExchangeObject同步
pbExchangeObject同步
函数,因为它们实际上是以原子方式交换两个文件的内容

从:

该函数允许程序 通过以下方式执行“安全保存”操作: 创建和编写一个全新的 文件并交换内容

交换之后,访问路径 将引用对方文件的数据 (也就是说,对相同的数据 最初提到的,现在是 另一个文件的)

在Mac OS X v10.0及更高版本中提供


啊,这很有趣,谢谢!不得不使用C方法有点奇怪,我觉得在Cocoa中一定有办法。但这是肯定的。这些方法从10.8开始就被弃用了。注意:“在Mac OS X v10.6和更高版本中可用。”这是一个很好的建议,但我不相信这种方法是合适的,因为它旨在保留被替换项的元数据。此外,options参数不接受任何指示它应该重写目标的标志,而不是bail,因为该路径/url上已经存在一个项。此外,仅在10.6上可用也不太好,我的lib需要支持10.5和iphoneos3+。Cocoa开发人员多年来一直采用的标准方式;-)@德瓦恩接球不错,我没接住@Billy如果你已经知道有错误,你想回滚,你不能简单地删除目标文件并用回滚替换它吗?@ctshryock!但是,如果这是我知道要替换现有文件的其他情况,我会遇到同样的问题。也许真正的答案是:将目标移动到temp,将新文件移到适当的位置,从temp中删除旧文件。为什么不在数据库中使用真正的SQLite事务呢?这与在数据库上操作无关,它可能是任何文件。作为记录,我确实使用了事务,我对一个特定的操作进行了回滚,在这个操作中,使用一个密钥和密码加密的数据库然后被重新设置密钥,这是一个潜在的破坏性操作,特别是在中断时。