4

我正在我的 android 应用程序中实现备份/恢复系统。

每隔几分钟就会进行一次自动备份。在我的应用程序被卸载然后再次安装后,我正在尝试从我的 sd 卡恢复我的数据库备份文件。

备份有效,但问题是:
每当用户再次安装我的应用程序时,都会出现找不到文件的异常,但是,如果用户关闭应用程序,然后再次打开它,恢复就很好了。不知何故,当应用程序首次启动时,恢复面临问题。

恢复必须在首次启动时进行。

注意: backupExists 函数返回 true。

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(backUpExists()){

        restoreDB();
      }
}
     private boolean backUpExists()
  {
    try{
        File sd = Environment.getExternalStorageDirectory();
        if (sd.canRead()){
            String backupDBPath = "myDB";
             File backupedDB = new File(sd, backupDBPath);
             if(backupedDB.exists()){
                 return true;
             }
        }
    } catch(Exception ex) {
         Toast.makeText(getBaseContext(), ex.toString(), Toast.LENGTH_LONG).show();
    }
        return false;
  }
  private void restoreDB()
  {
    try{
        File sd = Environment.getExternalStorageDirectory();
        File data = Environment.getDataDirectory();

        if (sd.canWrite()) {
            String restroredDBPath = "//data//myPackage//databases//myDB";
            String backupDBPath = "myDB";
            File restoredDB = new File(data, restroredDBPath);
            File backupedDB = new File(sd, backupDBPath);
                FileChannel src = new FileInputStream(backupedDB).getChannel();
                FileChannel dst = new FileOutputStream(restoredDB).getChannel();
                dst.transferFrom(src, 0, src.size());
                src.close();
                dst.close();
                Toast.makeText(getBaseContext(), restoredDB.toString(), Toast.LENGTH_LONG).show();

        }
    } catch (Exception e) {

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

回溯

09-09 22:49:50.931: I/Database(23206): sqlite returned: error code = 26, msg = statement aborts at 14: [SELECT COUNT(*) FROM Photos WHERE AlbumId=0] file is encrypted or is not a database
09-09 22:49:50.931: D/AndroidRuntime(23206): Shutting down VM
09-09 22:49:50.931: W/dalvikvm(23206): threadid=1: thread exiting with uncaught exception (group=0x4151c700)
09-09 22:49:50.931: E/AndroidRuntime(23206): FATAL EXCEPTION: main
09-09 22:49:50.931: E/AndroidRuntime(23206): net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
09-09 22:49:50.931: E/AndroidRuntime(23206):    at     net.sqlcipher.database.SQLiteQuery.native_fill_window(Native Method)
09-09 22:49:50.931: E/AndroidRuntime(23206):    at net.sqlcipher.database.SQLiteQuery.fillWindow(SQLiteQuery.java:73)
09-09 22:49:50.931: E/AndroidRuntime(23206):    at net.sqlcipher.database.SQLiteCursor.fillWindow(SQLiteCursor.java:290)
[snipped]
4

3 回答 3

18

请使用此代码,它可能会对您有所帮助......我用这种方式做了同样的事情

用于备份

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();
            Toast.makeText(getApplicationContext(), "Backup is successful to SD card", Toast.LENGTH_SHORT).show();
        }
    }
} catch (Exception e) {
}

用于恢复

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(backupDB).getChannel();
            FileChannel dst = new FileOutputStream(currentDB).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
            Toast.makeText(getApplicationContext(), "Database Restored successfully", Toast.LENGTH_SHORT).show();
        }
    }
} catch (Exception e) {
}

如果条件,您可以在文件通道中看到两者之间的一点差异。

于 2013-09-10T07:37:16.600 回答
3
try
{
    String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
    String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/CALC/Backup";
    //final 
    String inFileName = path+"/Calc_backup :"+date;
    File dbFile = new File(inFileName);
    FileInputStream fis = new FileInputStream(dbFile);


    /*File dir = new File(path);
    if(!dir.exists())
        dir.mkdirs();*/
    //Toast.makeText(getActivity(), "directory created @"+dir.getPath(), 2).show();

    // String outFileName = Environment.getExternalStorageDirectory()+"Calac/hems.txt";

    //String outFileName = path+"/"+date;
    String outFileName = "/data/data/com.special.ResideMenuDemo/databases/Calq";

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

    Toast.makeText(getActivity(), "Restore Successfully", 2).show();
    // Close the streams
    output.flush();
    output.close();
    fis.close();

}
catch(Exception e)
{
    e.printStackTrace();
}
于 2015-07-09T11:46:32.653 回答
0

我觉得问题在于阅读已经存在的数据库文件。您实际上并没有阅读它,代码只是在每次安装应用程序时创建一个新代码。您必须提供您所指的 db 文件的确切名称,以便在您的getExternalEvironment函数中读取它。

于 2013-09-14T15:01:14.387 回答