Search code examples
javaandroidsqliteandroid-fileenoent

Trying to copy SQLite database in Android and getting "No such file or directory"


I have a database and I want to copy it to SD Card to keep a backup and I found this code:

private void exportDB(){
    File sd = Environment.getExternalStorageDirectory();
    File data = Environment.getDataDirectory();
    FileChannel source=null;
    FileChannel destination=null;
    String currentDBPath = "/data/"+ "com.example.myapp" +"/databases/"+"mydatabase";
    String backupDBPath = "/storage/extSdCard/mydatabase";
    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();
    } catch(IOException e) {
        //e.printStackTrace();
        Toast.makeText(this, "Err:"+e, Toast.LENGTH_LONG).show();
    }
}

As I wrote in the title I get the No such file or directory ENOENT error when I try to do it.

Apparently the database should be stored right there. I've tried changing the path to a few different things but still nothing... I tried:

"/data/"+ "com.example.myapp" +"/"+"mydatabase.db"

and

"//data//"+ "com.example.myapp" +"//databases//"+"mydatabase"

Edit1: Also tried this and also doesn't work:

String currentDBPath = this.getDatabasePath("mydatabase").toString();

etc. nothing works and I also can't find a way to check the path in any way.

I basically have the database made, inserted a few rows into it and have some basic functions like add() and delete() etc. Am I missing something? I have no idea what else I can try.

Here's what logcat has to say about this:

01-18 11:34:46.215 10337-10337/com.example.myapp D/DBPATH: Database path is /data/data/com.example.myapp/databases/mydatabase.db

01-18 11:34:46.225 10337-10337/com.example.myapp W/System.err: java.io.FileNotFoundException: /data/data/com.example.myapp/databases/mydatabase.db: open failed: ENOENT (No such file or directory)

01-18 11:34:46.235 10337-10337/com.example.myapp W/System.err: at libcore.io.IoBridge.open(IoBridge.java:456)

01-18 11:34:46.235 10337-10337/com.example.myapp W/System.err: at java.io.FileInputStream.(FileInputStream.java:76)

01-18 11:34:46.235 10337-10337/com.example.myapp W/System.err: at com.example.myapp.TabsActivity.exportDB(TabsActivity.java:183)

01-18 11:34:46.235 10337-10337/com.example.myapp W/System.err: at com.example.myapp.TabsActivity.onOptionsItemSelected(TabsActivity.java:119)


Solution

  • As below the issue may not be with the database, rather it could be with the external storage and because the directories do not exist. The fix is to create the directories. Hopefully the following will work (did for me):-

        try {
            source = new FileInputStream(currentDB).getChannel();
            (new File(backupDB.getParent())).mkdirs(); //<<<<<<<<<<<<<< ADDED
            destination = new FileOutputStream(backupDB).getChannel();
            //destination.transferFrom(source, 0, source.size());
            source.close();
            destination.close();
        } catch(IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "Err:"+e, Toast.LENGTH_LONG).show();
        }
    
    • For testing I've commented out the transfer. P.S. ran OK with transfer.
    • There could also be issues due to permissions (my testing was on a genymotion emulator).
    • Just tested on a real device, the same error will occur if permission aren't granted.
    • Just tested on real device setting permissions in Manifest and also in code for versions > 23. Copy then worked. :-

    enter image description here

    This may be of use Storage permission error in Marshmallow


    Taking your code and adapting it as per (which checks the paths, see output) :-

    java.io.FileNotFoundException: /mnt/sdcard/storage/extSdCard/mydatabase: open failed: ENOENT (No such file or directory)

    private void exportDB(){
        File sd = Environment.getExternalStorageDirectory();
        File data = Environment.getDataDirectory();
        FileChannel source=null;
        FileChannel destination=null;
        String currentDBPath = "/data/"+ getPackageName() +"/databases/"+DatabaseHandler.DATABASE_NAME;
        String retreivedDBPAth = getDatabasePath(DatabaseHandler.DATABASE_NAME).getPath();
        String backupDBPath = "/storage/extSdCard/mydatabase";
        File currentDB = new File(data, currentDBPath);
        File backupDB = new File(sd, backupDBPath);
        File retrievedDB = new File(retreivedDBPAth);
        Log.d("PATHS", " CurrentDB=" +
                currentDBPath + "\n\t" + currentDB.getPath() +
                "\n\tExists=" + String.valueOf(currentDB.exists()) +
                "\nBackup=" + backupDBPath + "\n\t" + backupDB.getPath() +
                "\n\tExists=" + String.valueOf(backupDB.exists()) +
                "\nRetrieved DB=" + retreivedDBPAth + "\n\t" + retrievedDB.getPath() +
                "\n\tExists=" + String.valueOf(retrievedDB.exists())
        );
        try {
            source = new FileInputStream(currentDB).getChannel();
            destination = new FileOutputStream(backupDB).getChannel();
            //destination.transferFrom(source, 0, source.size());
            source.close();
            destination.close();
        } catch(IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "Err:"+e, Toast.LENGTH_LONG).show();
        }
    }
    

    The ENOENT is not for the database but for the External storage as per :-

    01-18 11:11:32.017 2689-2689/? D/PATHS:  CurrentDB=/data/example.com.so48304909_spinner/databases/spinnerExample
                                                /data/data/example.com.so48304909_spinner/databases/spinnerExample
                                                Exists=true
                                            Backup=/storage/extSdCard/mydatabase
                                                /mnt/sdcard/storage/extSdCard/mydatabase
                                                Exists=false
                                            Retrieved DB=/data/data/example.com.so48304909_spinner/databases/spinnerExample
                                                /data/data/example.com.so48304909_spinner/databases/spinnerExample
                                                Exists=true
    01-18 11:11:32.021 2689-2689/? W/System.err: java.io.FileNotFoundException: /mnt/sdcard/storage/extSdCard/mydatabase: open failed: ENOENT (No such file or directory)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:416)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at example.com.so48304909_spinner.MainActivity.exportDB(MainActivity.java:162)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at example.com.so48304909_spinner.MainActivity.onCreate(MainActivity.java:38)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at android.app.Activity.performCreate(Activity.java:5008)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at android.app.ActivityThread.access$600(ActivityThread.java:130)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:99)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at android.os.Looper.loop(Looper.java:137)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:4745)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at java.lang.reflect.Method.invokeNative(Native Method)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at java.lang.reflect.Method.invoke(Method.java:511)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at dalvik.system.NativeStart.main(Native Method)
    01-18 11:11:32.021 2689-2689/? W/System.err: Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at libcore.io.Posix.open(Native Method)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
    01-18 11:11:32.021 2689-2689/? W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:400)
    01-18 11:11:32.021 2689-2689/? W/System.err:    ... 18 more