【问题标题】:How do I backup a database file to the SD card on Android?如何将数据库文件备份到 Android 上的 SD 卡?
【发布时间】:2011-01-01 00:09:00
【问题描述】:

我想在我的 Android 应用程序中添加一项功能,自动将 SQLite 数据库备份到 SD card

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

【问题讨论】:

  • 请注意,如果它在 SD 卡上,它将不再对您的应用程序私有。
  • @Mirko N:我知道,但是人们想要一个备份副本以用于重新安装、手机损坏等类似的事情。

标签: database android backup sd-card


【解决方案1】:

此代码对我有用!

    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) {
    }

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

【讨论】:

  • 我可以确认这确实适用于无根手机。只要确保添加<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
  • currentDB.exists() returnign false.... 可能 b 该数据库不存在于 sys 内存中,但我已成功插入行...并且 m 通过 String currentDBPath = db 获取路径.getPath();
  • 我使用 File currentDB = getDatabasePath(DatabaseHelper.DATABASE_NAME);而不是静态引用
  • FileChannel src = new FileOutputStream(currentDB).getChannel(); FileChannel dst = new FileInputStream(backupDB).getChannel(); src.transferFrom(dst, 0, dst.size()); src.close(); dst.close();当我这样做时,数据库会丢失并创建一个新文件
  • 和恢复bd,会怎么样?对于非根设备
【解决方案2】:
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();
}

这与上面的例子相反,其中“/”是“\”浪费了我生命中的 20 分钟来弄清楚这一点,但我真的应该早点看到这一点。 Toast 会告诉你文件放在哪里,或者当它不起作用时告诉你出了什么问题。

【讨论】:

  • iif(sd.canWrite()) 对我不起作用。相反,我使用 if (Environment.MEDIA_MOUNTED.equals(state)) {
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • 我看到了你的例子,它看起来很简洁,好像太简洁了。我很难弄清楚如何使其适应我的代码。我不知道谁的代码效率更高,我只知道额外的逻辑/代码或过于简化的代码让我更难理解和适应我的代码。大多数人创建 4 个单独的“文件”,而您只创建 2 个文件。为什么这个特定主题如此令人困惑?
    【解决方案5】:
    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】:

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

      【讨论】:

        【解决方案7】:

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

        /Android/data/{package_name}/files/
        

        无论是否已root,这都会起作用。

        【讨论】:

        • 在sd卡上备份到这个位置的问题是卸载应用时会被删除。这可能不需要备份。
        【解决方案8】:

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

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

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

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

        出口

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

        进口

        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】:

          @skeniver's code 为我工作。我只想添加以下内容:

          用途:

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

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

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

          【讨论】:

            【解决方案10】:
            @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();
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-06-07
              • 2011-01-11
              • 2023-03-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多