2

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)

Community
  • 1
  • 1
  • Have you tried using `File currentdb = new File(this.getDatabasePath("mydatabase.db").getPath());`? - i.e. no parent, and getting the path NOT the object's toString value. This assumes the file name is mydatabase.db (if just mydatabase then use that). – MikeT Jan 18 '18 at 00:26
  • tried, doesn't work. I take it that if I create a database it automatically stores it in the data/.../databases/ right? I don't have to like put it there somehow do I? also what is the standard way it's stored? mydatabase or mydatabase.db? Sorry if this is a stupid question, I've never dealt with a database on android before. – Paulina Maz Jan 18 '18 at 10:03
  • By default Database is stored in `data/data/`*`package`*`/databases`, but it needn't be stored there. However, I'd suggest adding logging (e.g. `Log.d("DBPATH","Database path is " + currentDBPath);` or at least including the stack trace from the log (uncomment `//e.printStackTrace();`). The edit your question with results. – MikeT Jan 18 '18 at 10:13
  • just did that. My phone isn't rooted can this be the problem? – Paulina Maz Jan 18 '18 at 10:44
  • Uhhm not sure of that. However just answered you need to make the directories. However, I'm using Genymotion emulator which I think is rooted as such. So answer works for me. – MikeT Jan 18 '18 at 10:47
  • Considering your edit, use `File currentdb = new File(this.getDatabasePath("mydatabase.db").getPath());` or if that fails (using logging like in the answer) use `File currentdb = new File(this.getDatabasePath("mydatabase").getPath());`. – MikeT Jan 18 '18 at 10:55

1 Answers1

3

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
MikeT
  • 51,415
  • 16
  • 49
  • 68