2

在我的一个 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+。

4

3 回答 3

9

怎么样NSFileManagerreplaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:

在此处查看文档

于 2009-12-29T15:52:09.157 回答
3

C 级FSMoveObjectSync / FSMoveObjectAsync函数可能会有所帮助。这些函数采用一组选项,其中可以包括覆盖目标的标志kFSFileOperationOverwrite等等。

于 2009-12-29T15:35:01.210 回答
1

我建议使用FSExchangeObjects, PBExchangeObjectsSyncorPBExchangeObjectsAsync函数,因为它们实际上以原子方式交换两个文件的内容。

开发库

该功能允许程序通过创建和写入一个完整的新文件并交换内容来实现“安全保存”操作。

交换后,访问路径将引用对立文件的数据(即,它最初引用的相同数据,现在是另一个文件的一部分)。

在 Mac OS X v10.0 及更高版本中可用。

于 2011-03-11T18:53:37.187 回答