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

时间:2020-11-27 09:00:52

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

我想在我的Android应用程序中添加一个功能,可以自动将SQLite数据库备份到SD卡上。

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

最好的办法是什么?有范例或教程吗?

11 个解决方案

#1


7  

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()))。

#2


118  

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上试过。

#3


19  

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 Toast will tell you where the file has been place or tell you what's wrong when it doesn't work.

与上面的例子相反,“/”在我的生命中浪费了20分钟来计算,但我真的应该早点看到它。吐司将告诉您文件的位置,或者当它不起作用时告诉您哪里出了问题。

#4


2  

I answered a 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在适当的状态下对它进行数据库调用。

#5


2  

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();
    }
}

#6


1  

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.

这将会起作用,不管它是否扎根。

#7


1  

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

你得给许可,安德,许可。WRITE_EXTERNAL_STORAGE在您的应用程序。它在无根设备上运行良好。

#8


0  

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中这样做,但是要记住改变上下文。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();
        }
}

#9


0  

@skeniver's code works 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}";

#10


-1  

@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();
    }
}

#11


-2  

If success block give me an error on:

如果成功块给我一个错误:

String inFileName = context.getDatabasePath(DB-Name);
File dbFile = new File(inFileName);
FileInputStream fis = new FileInputStream(dbFile);

#1


7  

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()))。

#2


118  

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上试过。

#3


19  

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 Toast will tell you where the file has been place or tell you what's wrong when it doesn't work.

与上面的例子相反,“/”在我的生命中浪费了20分钟来计算,但我真的应该早点看到它。吐司将告诉您文件的位置,或者当它不起作用时告诉您哪里出了问题。

#4


2  

I answered a 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在适当的状态下对它进行数据库调用。

#5


2  

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();
    }
}

#6


1  

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.

这将会起作用,不管它是否扎根。

#7


1  

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

你得给许可,安德,许可。WRITE_EXTERNAL_STORAGE在您的应用程序。它在无根设备上运行良好。

#8


0  

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中这样做,但是要记住改变上下文。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();
        }
}

#9


0  

@skeniver's code works 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}";

#10


-1  

@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();
    }
}

#11


-2  

If success block give me an error on:

如果成功块给我一个错误:

String inFileName = context.getDatabasePath(DB-Name);
File dbFile = new File(inFileName);
FileInputStream fis = new FileInputStream(dbFile);