You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLite数据库备份遇FileNotFoundException问题求助

问题分析与解决方案

兄弟,我一眼就揪出了核心问题:你现在的代码是从Assets目录读取数据库,但你要备份的是已经运行起来、存在于应用私有数据目录(/data/data/你的包名/databases/)里的数据库,c.getAssets().open(Constants.DB_NAME)自然会找不到文件——Assets里的是APK打包时的原始数据库,不是你正在用的那个带数据的库!

下面给你一步步修正的方案:

1. 修正源数据库的读取路径

直接从应用的数据库目录读取已运行的数据库文件,用系统提供的方法获取正确路径,避免手动拼接出错:

String sourceDbPath = c.getDatabasePath(Constants.DB_NAME).getAbsolutePath();

这个方法会自动返回当前应用数据库的准确路径,不用自己写/data/data/xxx这种容易写错的字符串。

2. 确保目标目录存在

如果DB_PATH对应的目录还没创建,写入文件时会直接报错,所以先检查并创建目录:

File outDir = new File(DB_PATH);
if (!outDir.exists()) {
    outDir.mkdirs(); // 递归创建多级目录,不用怕目录嵌套
}

3. 修改完整的copyDataBase方法

把这些点整合起来,修改后的代码应该是这样的:

public void copyDataBase(String itinerario, Context c) throws IOException {
    // 1. 获取源数据库的正确路径并检查是否存在
    String sourceDbPath = c.getDatabasePath(Constants.DB_NAME).getAbsolutePath();
    File sourceDb = new File(sourceDbPath);
    if (!sourceDb.exists()) {
        throw new FileNotFoundException("源数据库不存在:" + sourceDbPath);
    }

    // 2. 准备目标路径并确保目录存在
    String outFileName = DB_PATH + Constants.DB_NAME + itinerario;
    File outDir = new File(DB_PATH);
    if (!outDir.exists()) {
        outDir.mkdirs();
    }

    // 3. 执行文件复制
    InputStream mInputStream = new FileInputStream(sourceDb);
    OutputStream mOutputStream = new FileOutputStream(outFileName);

    byte[] buffer = new byte[1024];
    int length;
    while ((length = mInputStream.read(buffer)) > 0) {
        mOutputStream.write(buffer, 0, length);
    }

    // 4. 关闭流(别漏了)
    mOutputStream.flush();
    mOutputStream.close();
    mInputStream.close();
}

额外优化:用try-with-resources自动管理流

为了避免忘记关闭流导致资源泄漏,推荐用Java 7+的try-with-resources语法,代码更简洁安全:

public void copyDataBase(String itinerario, Context c) throws IOException {
    String sourceDbPath = c.getDatabasePath(Constants.DB_NAME).getAbsolutePath();
    File sourceDb = new File(sourceDbPath);
    
    if (!sourceDb.exists()) {
        throw new FileNotFoundException("源数据库不存在:" + sourceDbPath);
    }
    
    String outFileName = DB_PATH + Constants.DB_NAME + itinerario;
    File outDir = new File(DB_PATH);
    if (!outDir.exists()) {
        outDir.mkdirs();
    }
    
    // try-with-resources会自动关闭流,不用手动写close()
    try (InputStream in = new FileInputStream(sourceDb);
         OutputStream out = new FileOutputStream(outFileName)) {
        
        byte[] buffer = new byte[1024];
        int length;
        while ((length = in.read(buffer)) > 0) {
            out.write(buffer, 0, length);
        }
        out.flush();
    }
}

最后再给你提个小建议:测试时可以打印sourceDbPath和outFileName的具体值,看看是不是路径里少了斜杠、拼错了包名这类低级错误——有时候眼睛真的会自动忽略这种细节!

内容的提问来源于stack exchange,提问作者Magobin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:38:30