【问题标题】:Error trying to copy from bundle to documents directory尝试从捆绑包复制到文档目录时出错
【发布时间】:2016-07-13 23:52:58
【问题描述】:

我已将一个 sqlite 文件添加到我的应用程序中,并尝试将其从捆绑包复制到文档目录。我也将 sqlite 添加到目标应用程序。以下是我用来复制文件的代码:

NSString *destination = [[[Utils applicationDocumentsDirectory] absoluteString] stringByAppendingString:@"myapp.sqlite"];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:destination]) {
        NSString *source = [[NSBundle mainBundle] pathForResource:@"myapp" ofType:@"sqlite"];
        NSError *error = nil;
        [fileManager copyItemAtPath:source toPath:destination error:&error];
        if (error) {
            //
        }
    }

[Utils applicationDocumentsDirectory] 的代码:

+ (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

但是当执行这段代码时,我得到以下error

错误域=NSCocoaErrorDomain Code=4 "文件“myapp.sqlite” 不存在。” UserInfo={NSSourceFilePathErrorKey=/Users/harikrishnan/Library/Developer/CoreSimulator/Devices/8E531314-F1AE-417F-8E99-7AA92967CDC9/data/Containers/Bundle/Application/0A710929-475D-457C-8D2D-C2F2BBEB6B92/myapp.app/ myapp.sqlite, NSUserStringVariant=( 复制),NSDestinationFilePath=file:///Users/harikrishnant/Library/Developer/CoreSimulator/Devices/8E531314-F1AE-417F-8E99-7AA92967CDC9/data/Containers/Data/Application/13B22E15-D00C-433C-9F02-014B1F73D183/文件/myapp.sqlite, NSFilePath=/Users/harikrishnant/Library/Developer/CoreSimulator/Devices/8E531314-F1AE-417F-8E99-7AA92967CDC9/data/Containers/Bundle/Application/0A710929-475D-457C-8D2D-C2F2BBEB6B92/myapp.app/myapp.sqlite , NSUnderlyingError=0x7faffe1b5cf0 {错误域=NSPOSIXErrorDomain Code=2 "没有这样的文件或目录"}}

我使用终端检查了以下路径,发现 sqlite 文件实际上存在于 app bundle 中:

/Users/harikrishnant/Library/Developer/CoreSimulator/Devices/8E531314-F1AE-417F-8E99-7AA92967CDC9/data/Containers/Bundle/Application/0A710929-475D-457C-8D2D-C2F2BBEB6B92/myapp.app/myapp. sqlite

但我仍然收到此错误。我什么都试过了。我什至清理了构建文件夹并重新安装了应用程序,它仍然无法正常工作。这里有什么问题?如何解决?

【问题讨论】:

  • 使用Utils applicationDocumentsDirectory 的代码更新您的问题。
  • @rmaddy 添加了代码。
  • 您获取文档 URL 的代码是正确的。但我建议您调用path 而不是absoluteStringNSURL 转换为路径字符串。
  • @rmaddy 成功了!!!!但是你能解释一下absoluteStringpath之间有什么区别吗?
  • 您还需要将stringByAppendingString: 更改为stringByAppendingPathComponent:

标签: ios objective-c nsfilemanager nsbundle


【解决方案1】:

您的代码几乎是正确的。这条线有两个缺陷:

NSString *destination = [[[Utils applicationDocumentsDirectory] absoluteString] stringByAppendingString:@"myapp.sqlite"];

absoluteString 的使用不正确。这给出了file://path/to/Documents/ 形式的文件URL。您需要使用path 方法从NSURL 获取文件路径(不是文件URL)。

然后您需要将文件名正确附加到路径中。您需要使用stringByAppendingPathComponent: 而不是stringByAppendingString:

那一行应该是:

NSString *destination = [[[Utils applicationDocumentsDirectory] path] stringByAppendingPathComponent:@"myapp.sqlite"];

【讨论】:

    【解决方案2】:

    我使用以下代码将我的 SQLite DB 从应用程序包复制到文档目录。
    注意“数据库”是文件夹名称。 'datasource' 是我的数据库名称,它的扩展名是 'db'

    -(void)saveDatabase{
            //put bundle database to DocumentDirectory
            NSLog(@"%@",[self databasePath]);
            //Create Path For Destination
            NSString* path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
            path = [path stringByAppendingPathComponent:@"Database"];
            BOOL isExists=[[NSFileManager defaultManager]fileExistsAtPath:path];
            if(!isExists){
                NSError* error;
                BOOL isCreated = [[NSFileManager defaultManager]createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error];
                if(isCreated){
                    path = [path stringByAppendingPathComponent:@"Datasource"];
                    path = [path stringByAppendingPathExtension:@"db"];
                    isExists = [[NSFileManager defaultManager]fileExistsAtPath:path];
                    if(!isExists){
                        NSError* dbError;
                        NSString* bundle = [[NSBundle mainBundle]pathForResource:@"Datasource" ofType:@"db"];
                        isCreated = [[NSFileManager defaultManager]copyItemAtPath:bundle toPath:path error:&dbError];
                        if(isCreated){
                            NSLog(@"DatabasePath %@",path);
                        }else{
                            NSLog(@"ErrorCopying DB file %@",dbError.localizedDescription);
                        }
                    }else{
    
                    }
    
                }else{
                    NSLog(@"Error While Creating Database Directory:->%@",error.localizedDescription);
                }
            }
        }
        - (NSString*)databasePath{
            NSString* path = [self documentDirectory];
            path = [path stringByAppendingPathComponent:@"Database"];
            path = [path stringByAppendingPathComponent:@"Datasource"];
            path = [path stringByAppendingPathExtension:@"db"];
            return path;
        }
        - (NSString*)documentDirectory{
            return [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
        }
    

    【讨论】:

    • 不,不要使用此代码。这不是获取 Documents 文件夹引用的正确方法。最重要的是,这段代码的逻辑很糟糕,不能正常工作。
    • @rmaddy 我并没有真正遵循逻辑,但获取路径的代码实际上帮助我解决了我的问题。
    • 这段代码有严重的缺陷。它的目录存在,但文件不存在,它不复制任何东西。使用NSHomeDirectory() 并附加“Documents”是获取 Documents 文件夹引用的错误方法。
    • @rmaddy,尊敬的先生,您能告诉我访问“文档”目录的正确方法吗?
    • 问题中发布的代码是获取 Documents 文件夹引用的正确方法。
    【解决方案3】:

    确保您的文件在您使用的目标中的Build Phases -> Copy Bundle Resources 中列出。尝试删除Derived data。如果仍然无法正常工作,请转到 Derived data 并使用 Finder 检查文件。

    【讨论】:

      猜你喜欢
      • 2016-03-24
      • 2011-05-02
      • 2012-04-07
      • 1970-01-01
      • 1970-01-01
      • 2013-03-29
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多