Simple export and import of a SQLite database on Android

JavaAndroidDatabaseSqlite

Java Problem Overview


I am trying to implement a simple SQLite export/import for backup purposes. Export is just a matter of storing a copy of the raw current.db file. What I want to do for import is to just delete the old current.db file and rename the imported.db file to current.db. Is this possible? When I try this solution, I get the following error:

06-30 13:33:38.831: ERROR/SQLiteOpenHelper(23570):
    android.database.sqlite.SQLiteDatabaseCorruptException: error code 11: database disk image is malformed

If I look at the raw database file in a SQLite browser it looks fine.

Java Solutions


Solution 1 - Java

I use this code in the SQLiteOpenHelper in one of my applications to import a database file.

EDIT: I pasted my FileUtils.copyFile() method into the question.

SQLiteOpenHelper

public static String DB_FILEPATH = "/data/data/{package_name}/databases/database.db";

/**
 * Copies the database file at the specified location over the current
 * internal application database.
 * */
public boolean importDatabase(String dbPath) throws IOException {

	// Close the SQLiteOpenHelper so it will commit the created empty
	// database to internal storage.
	close();
	File newDb = new File(dbPath);
	File oldDb = new File(DB_FILEPATH);
	if (newDb.exists()) {
		FileUtils.copyFile(new FileInputStream(newDb), new FileOutputStream(oldDb));
		// Access the copied database so SQLiteHelper will cache it and mark
		// it as created.
		getWritableDatabase().close();
		return true;
	}
	return false;
}

FileUtils

public class FileUtils {
    /**
	 * Creates the specified <code>toFile</code> as a byte for byte copy of the
	 * <code>fromFile</code>. If <code>toFile</code> already exists, then it
	 * will be replaced with a copy of <code>fromFile</code>. The name and path
	 * of <code>toFile</code> will be that of <code>toFile</code>.<br/>
	 * <br/>
	 * <i> Note: <code>fromFile</code> and <code>toFile</code> will be closed by
	 * this function.</i>
	 * 
	 * @param fromFile
	 *            - FileInputStream for the file to copy from.
	 * @param toFile
	 *            - FileInputStream for the file to copy to.
	 */
	public static void copyFile(FileInputStream fromFile, FileOutputStream toFile) throws IOException {
		FileChannel fromChannel = null;
		FileChannel toChannel = null;
		try {
			fromChannel = fromFile.getChannel();
			toChannel = toFile.getChannel();
			fromChannel.transferTo(0, fromChannel.size(), toChannel);
		} finally {
			try {
				if (fromChannel != null) {
					fromChannel.close();
				}
			} finally {
				if (toChannel != null) {
					toChannel.close();
				}
			}
		}
	}
}

Don't forget to delete the old database file if necessary.

Solution 2 - Java

This is a simple method to export the database to a folder named backup folder you can name it as you want and a simple method to import the database from the same folder a

    public class ExportImportDB extends Activity {
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		// TODO Auto-generated method stub
    		super.onCreate(savedInstanceState);
//creating a new folder for the database to be backuped to
    		File direct = new File(Environment.getExternalStorageDirectory() + "/Exam Creator");
    
    		   if(!direct.exists())
    		    {
    		        if(direct.mkdir()) 
    		          {
    		           //directory is created;
    		          }
    
    		    }
    		exportDB();
    		importDB();
    
    	}
    //importing database
    	private void importDB() {
    		// TODO Auto-generated method stub
    
    		try {
    			File sd = Environment.getExternalStorageDirectory();
    			File data  = Environment.getDataDirectory();
    
    			if (sd.canWrite()) {
    				String  currentDBPath= "//data//" + "PackageName"
    						+ "//databases//" + "DatabaseName";
    				String backupDBPath  = "/BackupFolder/DatabaseName";
    				File  backupDB= new File(data, currentDBPath);
    				File currentDB  = 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();
    
    		}
    	}
    //exporting database 
    	private void exportDB() {
    		// TODO Auto-generated method stub
    
    		try {
    			File sd = Environment.getExternalStorageDirectory();
    			File data = Environment.getDataDirectory();
    
    			if (sd.canWrite()) {
    				String  currentDBPath= "//data//" + "PackageName"
    						+ "//databases//" + "DatabaseName";
    				String backupDBPath  = "/BackupFolder/DatabaseName";
    				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();
    
    		}
    	}
    
    }

Dont forget to add this permission to proceed it

  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
    </uses-permission>

Enjoy

Solution 3 - Java

To export db rather it is SQLITE or ROOM:

Firstly, add this permission in AndroidManifest.xml file:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Secondly, we drive to code the db functions:

private void exportDB() {
    try {
        File dbFile = new File(this.getDatabasePath(DATABASE_NAME).getAbsolutePath());
        FileInputStream fis = new FileInputStream(dbFile);

        String outFileName = DirectoryName + File.separator +
                DATABASE_NAME + ".db";

        // 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);
        }
        // Close the streams
        output.flush();
        output.close();
        fis.close();


    } catch (IOException e) {
        Log.e("dbBackup:", e.getMessage());
    }
}

Create Folder on Daily basis with name of folder is Current date:

public void createBackup() {

    sharedPref = getSharedPreferences("dbBackUp", MODE_PRIVATE);
    editor = sharedPref.edit();

    String dt = sharedPref.getString("dt", new SimpleDateFormat("dd-MM-yy").format(new Date()));

    if (dt != new SimpleDateFormat("dd-MM-yy").format(new Date())) {
        editor.putString("dt", new SimpleDateFormat("dd-MM-yy").format(new Date()));

        editor.commit();
    }

    File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "BackupDBs");
    boolean success = true;
    if (!folder.exists()) {
        success = folder.mkdirs();
    }
    if (success) {

        DirectoryName = folder.getPath() + File.separator + sharedPref.getString("dt", "");
        folder = new File(DirectoryName);
        if (!folder.exists()) {
            success = folder.mkdirs();
        }
        if (success) {
            exportDB();
        }
    } else {
        Toast.makeText(this, "Not create folder", Toast.LENGTH_SHORT).show();
    }

}

>Assign the DATABASE_NAME without .db extension and its data type is string

Solution 4 - Java

Import and Export of a SQLite database on Android

Here is my function for export database into device storage

private void exportDB(){
    String DatabaseName = "Sycrypter.db";
    File sd = Environment.getExternalStorageDirectory();
    File data = Environment.getDataDirectory();
    FileChannel source=null;
    FileChannel destination=null;
    String currentDBPath = "/data/"+ "com.synnlabz.sycryptr" +"/databases/"+DatabaseName ;
    String backupDBPath = SAMPLE_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, "Your Database is Exported !!", Toast.LENGTH_LONG).show();
    } catch(IOException e) {
        e.printStackTrace();
    }
}

Here is my function for import database from device storage into android application

private void importDB(){
    String dir=Environment.getExternalStorageDirectory().getAbsolutePath();
    File sd = new File(dir);
    File data = Environment.getDataDirectory();
    FileChannel source = null;
    FileChannel destination = null;
    String backupDBPath = "/data/com.synnlabz.sycryptr/databases/Sycrypter.db";
    String currentDBPath = "Sycrypter.db";
    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, "Your Database is Imported !!", Toast.LENGTH_SHORT).show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Solution 5 - Java

If you want this in kotlin . And perfectly working

 private fun exportDbFile() {

    try {

        //Existing DB Path
        val DB_PATH = "/data/packagename/databases/mydb.db"
        val DATA_DIRECTORY = Environment.getDataDirectory()
        val INITIAL_DB_PATH = File(DATA_DIRECTORY, DB_PATH)

        //COPY DB PATH
        val EXTERNAL_DIRECTORY: File = Environment.getExternalStorageDirectory()
        val COPY_DB = "/mynewfolder/mydb.db"
        val COPY_DB_PATH = File(EXTERNAL_DIRECTORY, COPY_DB)

        File(COPY_DB_PATH.parent!!).mkdirs()
        val srcChannel = FileInputStream(INITIAL_DB_PATH).channel

        val dstChannel = FileOutputStream(COPY_DB_PATH).channel
        dstChannel.transferFrom(srcChannel,0,srcChannel.size())
        srcChannel.close()
        dstChannel.close()

    } catch (excep: Exception) {
        Toast.makeText(this,"ERROR IN COPY $excep",Toast.LENGTH_LONG).show()
        Log.e("FILECOPYERROR>>>>",excep.toString())
        excep.printStackTrace()
    }

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionandroid_sqliteView Question on Stackoverflow
Solution 1 - JavaAustyn MahoneyView Answer on Stackoverflow
Solution 2 - JavaYasin HassanienView Answer on Stackoverflow
Solution 3 - JavaAli Azaz AlamView Answer on Stackoverflow
Solution 4 - JavaMalith IleperumaView Answer on Stackoverflow
Solution 5 - JavaRANAJEET BARIKView Answer on Stackoverflow