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

时间:2009-12-29 15:22:10

标签: cocoa macos nsfilemanager

在我的cocoa应用程序中,有一种方法可以对sqlite数据库的模式执行一些可能具有破坏性的操作,因此首先我们制作数据库的回滚副本,如果有错误,我们调用以下方法用rollback文件替换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];

当发现目标路径上已存在文件时,最接近此barf的方法。

基于目前为止的回复的小更新:

传统上Cocoa开发者必须采用一些标准方式来原子地替换文件。 NSFileManager的各种“移动”方法不提供开箱即用的功能。此外,希望在此lib以及iPhone OS 3 +中支持10.5及更高版本。

3 个答案:

答案 0 :(得分:9)

NSFileManager的{​​{1}}怎么样?

See documentation here

答案 1 :(得分:3)

C级FSMoveObjectSync / FSMoveObjectAsync功能可能有所帮助。这些函数采用一组选项,其中包括flag to overwrite the destinationkFSFileOperationOverwrite等。

答案 2 :(得分:1)

我建议FSExchangeObjectsPBExchangeObjectsSyncPBExchangeObjectsAsync函数,因为它们实际上原子地交换了两个文件的内容。

来自development library

  

该功能允许程序   实施“安全保存”操作   创造和写作一个全新的   归档并交换内容。

     

交换后,访问路径   将引用相反文件的数据   (也就是说,它是相同的数据   最初提到的,现在是其中的一部分   另一个文件)。

     

适用于Mac OS X v10.0及更高版本。