美文网首页
Android 将数据库移植到Sdcard

Android 将数据库移植到Sdcard

作者: Lesss | 来源:发表于2019-08-25 18:37 被阅读0次

    app默认的数据库目录是在 data/data/your package/databases目录下,为什么我们需求将数据库移植到sdcard目录下呢,主要是为了解决 用户卸载在安装app数据丢失的问题 如果能移植到sdcard目录下 那么增加了数据的安全性,其实数据库移植无非就是文件的拷贝过程 直接上代码

    private static void copy(File currentDb, File backUpDb) {
    try {
    File sd = Environment.getExternalStorageDirectory();
    if (sd.canWrite()) {
    if (currentDb.exists()) {
    FileChannel src = new FileInputStream(currentDb).getChannel();
    FileChannel dst = new FileOutputStream(backUpDb).getChannel();
    dst.transferFrom(src, 0, src.size());
    src.close();
    dst.close();
    DBLog.p("dataFile:" + currentDb.length());
    DBLog.p("sdcardFile:" + backUpDb.length());
    } else {
    DBLog.p("currentDb not exists");
    }
    } else {
    DBLog.p("sdcard not write");
    }
    } catch (Exception e) {
    DBLog.p("copy-e:" + e.getMessage());
    }
    }

    下面以greendao为例子,将数据库拷贝之后 需要把默认的读取路径进行更换
    需要自己定义一个 DaoContext 实现getDatabasePath方法即可
    public class DaoContext extends ContextWrapper

    通常情况下这一系列操作是没有什么问题 但是sqlite-v3.7.0之后引入了新的事务设计WAL(Write-Ahead Logging)
    修改数据库时会在数据库目录下生成”-wal”和”-shm”两个文件,而且数据库文件并不会实时修改(文件时间戳不变),如果修改数据库之后立刻将数据库文件拷贝到其他目录,查看数据库会发现仍然是过期的旧数据,原因是sqlite把对数据库的修改缓存在”-wal”和”-shm”两个文件中了。

    总结下 也就是
    v3.7.0之前的数据文件方案,通过一个Journal文件来保证事务即使在断电情况下保持原子性,每次开启一个事务时,首先向Journal文件写入需要修改page的原内容,并且flush到硬盘,然后向数据库文件写入新的内容,最后删掉Journal文件中的内容完成一次事务。

    但要注意SQLite的Journal设计与ext3的Journal设计不一样,ext3的Journal保存的是全量可重做日志,SQLite恢复是备份恢复,ext3恢复时是重做流水日志

    v3.7.0之后的数据文件方案,首先把修改内容写入日志(-wal),为了提高性能创建一个内存索引(-shm),映射每一个page是否dirty,读取时先看需要的page是否在WAL日志中,然后再读取。当达到一定条件后SQLite会自动将数据flush到数据库文件,也可以通过命令或接口手动flush到数据库文件。

    那如何解决呢 大概的思路是 在拷贝数据库之前 先将wal的数据推入到主数据库中
    直接上代码 execSQL("PRAGMA wal_checkpoint(FULL)")

    相关文章

      网友评论

          本文标题:Android 将数据库移植到Sdcard

          本文链接:https://www.haomeiwen.com/subject/rlrkectx.html