如何在 Android 上将数据库文件备份到 SD 卡?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1995320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:06:36  来源:igfitidea点击:

How do I backup a database file to the SD card on Android?

databaseandroidbackupsd-card

提问by CodeFusionMobile

I'd like to add a feature to my Android app that automatically backs up the SQLitedatabase to the SD card.

我想向我的 Android 应用程序添加一项功能,该功能会自动将SQLite数据库备份到SD 卡

What's the best way to go about this? Are any examples or tutorials available?

解决这个问题的最佳方法是什么?是否有可用的示例或教程?

采纳答案by Christopher Orr

SQLite databases are completely self-contained files and are portable — you can just copy the entire file straight to the SD card.

SQLite 数据库是完全独立的文件并且是可移植的——您只需将整个文件直接复制到 SD 卡即可。

Though first I'd check whether an SD card is installed in the device, and what its path is (using Environment.getExternalStorageDirectory()).

虽然首先我会检查设备中是否安装了 SD 卡,以及它的路径是什么(使用Environment.getExternalStorageDirectory())。

回答by skeniver

This code works for me!

这段代码对我有用!

    try {
        File sd = Environment.getExternalStorageDirectory();
        File data = Environment.getDataDirectory();

        if (sd.canWrite()) {
            String currentDBPath = "//data//{package name}//databases//{database name}";
            String backupDBPath = "{database name}";
            File currentDB = new File(data, currentDBPath);
            File backupDB = new File(sd, backupDBPath);

            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();
            }
        }
    } catch (Exception e) {
    }

Does anyone know if this will work on non-root phones? I have only tried it on a rooted G1.

有谁知道这是否适用于非root手机?我只在有根的 G1 上试过。

回答by Rhys

try {
    File sd = Environment.getExternalStorageDirectory();
    File data = Environment.getDataDirectory();

    if (sd.canWrite()) {
        String currentDBPath = "//data//"+ packageName +"//databases//"+dbList[0];
        String backupDBPath = dbList[0];
        File currentDB = new File(data, currentDBPath);
        File backupDB = new File(sd, backupDBPath);

        FileChannel src = new FileInputStream(currentDB).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();
}

That works as opposed to the above examples in which the "/" are "\" wasted 20 minutes of my life figuring that out, but I really should have seen that sooner. The Toastwill tell you where the file has been place or tell you what's wrong when it doesn't work.

这与上面的例子相反,在上面的例子中,“/”是“\”浪费了我生命中的 20 分钟来弄清楚这一点,但我真的应该早点看到。该Toast会告诉你该文件已经到位或告诉你什么是错误的,当它不工作。

回答by Osama Ibrahim

public static void BackupDatabase() throws IOException
{
    boolean success =true;
    File file = null;
    file = new File(Environment.getExternalStorageDirectory() +"/M.O.L.S_Backup");

    if (file.exists())
    {
        success =true;
    }
    else
    {
        success = file.mkdir();
    }

    if (success)
    {
        String inFileName = "/data/data/com.sygic.sdk.demo/databases/MOLS_DB.s3db";
        File dbFile = new File(inFileName);
        FileInputStream fis = new FileInputStream(dbFile);

        String outFileName = Environment.getExternalStorageDirectory()+"/M.O.L.S_Backup/MOLS_DB.s3db";

        // Open the empty db as the output stream
        OutputStream output = new FileOutputStream(outFileName);

        // Transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = fis.read(buffer))>0) {
            output.write(buffer, 0, length);
        }

        output.flush();
        output.close();
        fis.close();
    }
}

回答by Austyn Mahoney

I answereda question similar to this with a method you can place in your SQLiteOpenHelper. It is as simple as copying the db file from some kind of external storage, to the internal application storage. There is also some extra code that opens and reads the db file to make sure it is in the proper state for Android to make database calls to it.

我用一种方法回答了一个与此类似的问题,您可以在SQLiteOpenHelper. 它就像将 db 文件从某种外部存储复制到内部应用程序存储一样简单。还有一些额外的代码可以打开并读取 db 文件,以确保它处于正确的状态,Android 可以对其进行数据库调用。

回答by Tushar Jadhav

You have to give the permission android.permission.WRITE_EXTERNAL_STORAGEin your application. It works fine on unrooted devices.

您必须android.permission.WRITE_EXTERNAL_STORAGE在应用程序中授予权限。它在无根设备上运行良好。

回答by ORY

You find your Database Name in the Database Adapter if you are new into this.

如果您是新手,您可以在数据库适配器中找到您的数据库名称。

Note that you can do this for SharedPreferences too but keep in mind to change your Context.MODE_PRIVATE to Context.MODE_MULTI_PROCESS.

请注意,您也可以为 SharedPreferences 执行此操作,但请记住将 Context.MODE_PRIVATE 更改为 Context.MODE_MULTI_PROCESS。

SharedPreferences_name should look like this = ExportSP("temp.xml");

SharedPreferences_name 应如下所示 = ExportSP("temp.xml");

String currentPathForSharedPreferences = "/data/"+ context.getPackageName() +"/shared_prefs/"+ SharedPreferences_name;

For export

出口

exportDB("MyDbName");

private void exportDB(String db_name){

File sd = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + 
                File.separator + "Your Backup Folder"+ 
                File.separator );

          boolean success = true;
           if (!sd.exists()) {
               success = sd.mkdir();
           }
           if (success) {

        File data = Environment.getDataDirectory();
       FileChannel source=null;
       FileChannel destination=null;
       String currentDBPath = "/data/"+ context.getPackageName() +"/databases/"+db_name;
       String backupDBPath = db_name;
       File currentDB = new File(data, currentDBPath);
       File backupDB = new File(sd, backupDBPath);
       try {
            source = new FileInputStream(currentDB).getChannel();
            destination = new FileOutputStream(backupDB).getChannel();
            destination.transferFrom(source, 0, source.size());
            source.close();
            destination.close();
            Toast.makeText(this, "Please wait", Toast.LENGTH_SHORT).show();
        } catch(IOException e) {
            e.printStackTrace();
        }
           }}

For import

进口

importDB("MyDbName");

private void importDB(String db_name){
        File sd = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + 
                File.separator + "Your Backup Folder"+ 
                File.separator );
        File data = Environment.getDataDirectory();
       FileChannel source=null;
       FileChannel destination=null;
       String backupDBPath = "/data/"+ context.getPackageName() +"/databases/"+db_name;
       String currentDBPath = db_name;
       File currentDB = new File(sd, currentDBPath);
       File backupDB = new File(data, backupDBPath);
       try {
            source = new FileInputStream(currentDB).getChannel();
            destination = new FileOutputStream(backupDB).getChannel();
            destination.transferFrom(source, 0, source.size());
            source.close();
            destination.close();
            Toast.makeText(this, "Please wait", Toast.LENGTH_SHORT).show();
        } catch(IOException e) {
            e.printStackTrace();
        }
}

回答by JMA

I don't know what happens if the phone is rooted or not but you should write your files to:

我不知道手机是否植根会发生什么,但您应该将文件写入:

/Android/data/{package_name}/files/

This will work whether it's rooted or not.

无论它是否扎根,这都将起作用。

回答by Charles Gouws

@skeniver's codeworks for me. I just want to add the following:

@skeniver 的代码对我有用。我只想添加以下内容:

Use:

用:

String currentDbPath = getApplicationContext().getDatabasePath("{database name}");

It will give you your database path. It is better to use that instead of hardcoding the path, like:

它会给你你的数据库路径。最好使用它而不是硬编码路径,例如:

String currentDbPath = "//data//{package name}//databases//{database name}";

回答by Jose Juarez

@Override
protected void onCreate(Bundle savedInstanceState) {
    try {
        File sd = Environment.getExternalStorageDirectory();
        File data = Environment.getDataDirectory();

        if (sd.canWrite()) {
            String currentDBPath = "//data//"+getPackageName()+"//databases//"+DATABASE_NAME+"";
            String backupDBPath = "backup.db";
            File currentDB = new File(data, currentDBPath);
            File backupDB = new File(sd, backupDBPath);

            FileChannel src = new FileInputStream(currentDB).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();
    }
}