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
相关产品推荐
相关产品推荐

