数据库导入和导出在Android Pie中不起作用

发布于 2021-01-30 17:32:39

以下是导入和导出SQLite数据库的工作方法。它的工作在除Android Pie外的所有android版本中都可以正常工作。当我尝试导入Android
Pie时,它显示成功的Toast,但未还原数据库。谁能帮我解决Android Pie(API 28)问题。

private void importDB() {

    try {
        File sd = Environment.getExternalStorageDirectory();
        File cur_db_pat = new File(this.getDatabasePath(DATABASE_NAME).getAbsolutePath());

        if (sd.canWrite()) {
            String backupDBPath = bac_dir_nam +"/" + DATABASE_NAME;
            File currentDB = new File(sd, backupDBPath);

            FileChannel src = new FileInputStream(currentDB).getChannel();
            FileChannel dst = new FileOutputStream(cur_db_pat).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
            Toast.makeText(getBaseContext(), cur_db_pat.toString(),
                    Toast.LENGTH_LONG).show();
        }
    } catch (Exception e) {

        Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG)
                .show();

    }
}

private void exportDB() {

    try {
        File sd = Environment.getExternalStorageDirectory();
        File cur_db_pat = new File(this.getDatabasePath(DATABASE_NAME).getAbsolutePath());

        if (sd.canWrite()) {
            String backupDBPath = bac_dir_nam+"/" + DATABASE_NAME;
            File backupDB = new File(sd, backupDBPath);

            FileChannel src = new FileInputStream(cur_db_pat).getChannel();
            FileChannel dst = new FileOutputStream(backupDB).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
            Toast.makeText(getBaseContext(), backupDB.toString(),
                    Toast.LENGTH_LONG).show();

        }
    } catch (Exception e) {

        Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG)
                .show();

    }
}

我对文件系统没有太多经验。因此,举个例子会很有帮助。

关注者
0
被浏览
93
1 个回答
  • 面试哥
    面试哥 2021-01-30
    为面试而生,有面试问题,就找面试哥。

    在Android Pie +中,SQLite已更改为默认设置,以使用通常更有效的预写日志记录( WAL )代替日记模式。

    这样,将有两个与数据库同名的文件,但后缀为 -shm (共享内存文件)和 -wal
    写日志),我认为它们的存在是导致此问题的原因。
    SQLite使用的临时文件(请参阅2.2和2.3)

    一种解决方法是使用SQliteDatabase disableWriteAheadLogging
    方法禁用预写日志记录,而先前的方法将像以前一样工作,但日志效率较低。

    • (如果使用 SQliteOpenHelper 的子类,则重写 onConfigure 方法以调用此方法。)disableWriteAheadLogging

    另一个修复方法是在还原时删除这两个文件。为了避免潜在的损坏,必须在进行备份之前确保对数据库进行适当的检查。见PRAGMA检查站;

    以下是还原时删除这两个文件的摘要(请注意,假定已使用足够的检查点进行了备份):

                        // Added for Android 9+ to delete shm and wal file if they exist
                        File dbshm = new File(dbfile.getPath() + "-shm");
                        File dbwal = new File(dbfile.getPath()+ "-wal");
                        if (dbshm.exists()) {
                            dbshm.delete();
                        }
                        if (dbwal.exists()) {
                            dbwal.delete();
                        }
    

    另一个解决方法是另外备份并随后还原-shm和-wal文件。

    您可能还希望考虑在导入/还原时重命名原始文件,在复制新文件后检查新文件的潜在好处(例如,使用 PRAGMA
    integrity_check;
    ),如果结果表明没有问题,则删除重命名的原始文件,否则删除导入的文件并将原始文件重命名为其原始名称,表明导入失败。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看