Android:当存在wal时,执行在更新到数据后复制db文件不起作用

时间:2013-01-25 02:46:17

标签: android database copy

我有一个具有备份和还原功能的应用。单击要备份的按钮会将db文件复制到外部存储。单击还原按钮将从外部存储(如果存在)中获取该文件并将其复制到应用程序中,并使用备份db文件覆盖现有数据库。

我在对表执行更新时遇到此问题。使用数据更新表后,具有更新数据的数据库将不会复制到外部存储中,或者如果我在更新后尝试还原,则不会复制该文件。

保存项目时,将打开数据库,然后调用以下函数执行更新,然后关闭数据库。

public void saveItem(int ItemID, int ItemNumber, String itemnote) 

{

        ContentValues args = new ContentValues();
        args.put("ItemNote", itemnote);
    mDb.update("Items", args, "ItemID =" + Item+" and ItemNumber ="+ItemNumber, null);

}

更新发生后,是什么阻止了db文件被复制?

我使用以下代码将db备份导入应用程序。同样,这一切都在执行更新语句之前有效。提前谢谢。

importdb.setOnClickListener(new View.OnClickListener(){             public void onClick(查看arg0){

            final File DATA_DIRECTORY_DATABASE = getDatabasePath("MyDB");

            final File DATABASE_DIRECTORY = new File(Environment.getExternalStorageDirectory(),"/MyApp");
            final File IMPORT_FILE = new File(DATABASE_DIRECTORY,"MyDB");

            File exportFile = DATA_DIRECTORY_DATABASE;

            File importFile = IMPORT_FILE;


            try {
                exportFile.createNewFile();
                copyFile(importFile, exportFile);
                Log.i("Import", "Succesfull");

            } catch (IOException e) {
                e.printStackTrace();

            }       




        }

    });

private static void copyFile(File src, File dst) throws IOException {
    FileChannel inChannel = new FileInputStream(src).getChannel();
    FileChannel outChannel = new FileOutputStream(dst).getChannel();
    try {
        inChannel.transferTo(0, inChannel.size(), outChannel);
    } finally {
        if (inChannel != null)
            inChannel.close();
        if (outChannel != null)
            outChannel.close();
    }
}

3 个答案:

答案 0 :(得分:0)

我认为数据库版本没有改变,这就是代码无法正常工作的原因。

答案 1 :(得分:0)

如果未关闭数据库连接,则SQLite可能仍会锁定数据库文件;因此阻止其复制。

如果您使用多个线程,那么即使关闭数据库连接,SQLite也可能没有时间关闭数据库并在第二个线程尝试复制之前释放锁。

答案 2 :(得分:0)

在不同设备上进行大量测试并查看日志文件之后。据发现,在某些设备上,数据库处于预写日志记录模式(wal)。这不是所有的设备,但是在我的一个测试设备HTC Droid Incredible上,启用了wal,其中没有启用点火器。

在没有启用wal的设备上,没有问题。在具有wal的设备上,数据的导入和导出不起作用,因为实际的db文件不是最新的,因为任何更改都驻留在wal文件中,并且在命中wal的检查点之前不会提交到db文件。

为了确保导入和导出功能正常工作,我需要db包含最新信息。为此,需要运行sqlite语句来执行wal检查点,该检查点将所有信息提交给db文件。

在运行导出或导入功能之前,执行以下sqlite命令以启动检查点并清除wal并将更改提交到数据库。

PRAGMA wal_checkpoint

调用检查点后,功能正常运行