Skip to content Skip to sidebar Skip to footer

Having Trouble Copying An Existing Sqlite Db File From Assets To Android Project

I have the following code: private void copyDataBase() throws IOException { Context context = this.getApplicationContext(); // Open your local db as the input stream I

Solution 1:

I believe that your issue is that the databases folder doesn't exist. Rather just /data/data/<the_package>/ exists.

So try adding the code as per the comments :-

Fileoutfile=newFile(context.getDatabasePath(DB_NAME).toString()); //<<<<<<<<< EXISTING LINEif (!outfile.getParentFile().exists()) { //<<<<<<<<<< ADDED
    outfile.getParentFile().mkdirs(); //<<<<<<<<<< ADDED
} //<<<<<<<<<< ADDED

I tend do the directory creation in when checking to see if the database exists e.g. :-

privatebooleancheckDataBase() {
    /**
     * Does not open the database instead checks to see if the file exists
     * also creates the databases directory if it does not exist
     * (the real reason why the database is opened, which appears to result in issues)
     */Filedb=newFile(myContext.getDatabasePath(DB_NAME).getPath()); //Get the file name of the databaseif (db.exists()) returntrue; // If it exists then return doing nothing// Get the parent (directory in which the database file would be)Filedbdir= db.getParentFile();
    // If the directory does not exist then make the directory (and higher level directories if need be)if (!dbdir.exists()) {
        dbdir.mkdirs();
    }
    returnfalse;
}

Replicating the Issue

Using the code :-

privatevoidcopyDataBase()throws IOException {

        finalStringTAG="COPYDATABASE";

        //Open your local db as the input stream
        Log.d(TAG,"Initiated Copy of the database file " + DB_NAME + " from the assets folder.");
        InputStreammyInput= myContext.getAssets().open(DB_NAME); // Open the Asset fileStringdbpath= myContext.getDatabasePath(DB_NAME).getPath();
        Log.d(TAG,"Asset file " + DB_NAME + " found so attmepting to copy to " + dbpath);

        // Path to the just created empty db//String outFileName = DB_PATH + DB_NAME;//Open the empty db as the output streamFileoutfile=newFile(myContext.getDatabasePath(DB_NAME).toString());
        Log.d("DBPATH","path is " + outfile.getPath());
        outfile.setWritable(true);
        //OutputStream myoutputx2 = new FileOutputStream(outfile);if (!outfile.getParentFile().exists()) {
            outfile.getParentFile().mkdirs();
        }

        OutputStreammyOutput=newFileOutputStream(outfile);
        //transfer bytes from the inputfile to the outputfilebyte[] buffer = newbyte[buffer_size];
        int length;
        while ((length = myInput.read(buffer))>0) {
            blocks_copied++;
            Log.d(TAG,"Ateempting copy of block " + String.valueOf(blocks_copied) + " which has " + String.valueOf(length) + " bytes.");
            myOutput.write(buffer, 0, length);
            bytes_copied += length;
        }
        Log.d(TAG,
                "Finished copying Database " + DB_NAME +
                        " from the assets folder, to  " + dbpath +
                        String.valueOf(bytes_copied) + "were copied, in " +
                        String.valueOf(blocks_copied) + " blocks of size " +
                        String.valueOf(buffer_size) + "."
        );
        //Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
        Log.d(TAG,"All Streams have been flushed and closed.");
    }

Results in the error you are getting as per :-

02-21 10:17:25.975 7604-7604/so.cdfa D/VERSION: Build Version is 22
02-21 10:17:25.975 7604-7604/so.cdfa D/DBPATH: DB Path is /data/data/so.cdfa/databases/db
02-21 10:17:25.975 7604-7604/so.cdfa D/DBPATH: DB Path is /data/data/so.cdfa/databases/db
02-21 10:17:25.976 7604-7604/so.cdfa D/COPYDATABASE: Initiated Copy of the database file db from the assets folder.
02-21 10:17:25.976 7604-7604/so.cdfa D/COPYDATABASE: Asset file db found so attmepting to copy to /data/data/so.cdfa/databases/db
02-21 10:17:25.976 7604-7604/so.cdfa D/DBPATH: path is /data/data/so.cdfa/databases/db
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err: java.io.FileNotFoundException: /data/data/so.cdfa/databases/db: open failed: ENOENT (No such file or directory)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:456)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at so.cdfa.DBHelper.copyDataBase(DBHelper.java:120)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at so.cdfa.DBHelper.createDataBase(DBHelper.java:58)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at so.cdfa.DBHelper.<init>(DBHelper.java:32)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at so.cdfa.MainActivity.onCreate(MainActivity.java:60)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.Activity.performCreate(Activity.java:5990)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
02-21 10:17:25.976 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread.access$800(ActivityThread.java:151)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at android.os.Looper.loop(Looper.java:135)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5254)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at java.lang.reflect.Method.invoke(Method.java:372)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at libcore.io.Posix.open(Native Method)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:442)
02-21 10:17:25.977 7604-7604/so.cdfa W/System.err:  ... 19 more
02-21 10:17:25.977 7604-7604/so.cdfa D/AndroidRuntime: Shutting down VM
02-21 10:17:25.977 7604-7604/so.cdfa E/AndroidRuntime: FATAL EXCEPTION: main
    Process: so.cdfa, PID: 7604
    java.lang.RuntimeException: Unable to start activity ComponentInfo{so.cdfa/so.cdfa.MainActivity}: java.lang.RuntimeException: Error copying database (see stack-trace above)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
        at android.app.ActivityThread.access$800(ActivityThread.java:151)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
     Caused by: java.lang.RuntimeException: Error copying database (see stack-trace above)
        at so.cdfa.DBHelper.createDataBase(DBHelper.java:65)

Amending the code to (as per the original answer):-

privatevoidcopyDataBase()throws IOException {

    finalStringTAG="COPYDATABASE";

    //Open your local db as the input stream
    Log.d(TAG,"Initiated Copy of the database file " + DB_NAME + " from the assets folder.");
    InputStreammyInput= myContext.getAssets().open(DB_NAME); // Open the Asset fileStringdbpath= myContext.getDatabasePath(DB_NAME).getPath();
    Log.d(TAG,"Asset file " + DB_NAME + " found so attmepting to copy to " + dbpath);

    // Path to the just created empty db//String outFileName = DB_PATH + DB_NAME;//Open the empty db as the output streamFileoutfile=newFile(myContext.getDatabasePath(DB_NAME).toString());
    Log.d("DBPATH","path is " + outfile.getPath());
    outfile.setWritable(true); //<<<<<<<<<< not required as writable access exists//OutputStream myoutputx2 = new FileOutputStream(outfile);if (!outfile.getParentFile().exists()) {
        outfile.getParentFile().mkdirs();
    }

    OutputStreammyOutput=newFileOutputStream(outfile);
    //transfer bytes from the inputfile to the outputfilebyte[] buffer = newbyte[buffer_size];
    int length;
    while ((length = myInput.read(buffer))>0) {
        blocks_copied++;
        Log.d(TAG,"Ateempting copy of block " + String.valueOf(blocks_copied) + " which has " + String.valueOf(length) + " bytes.");
        myOutput.write(buffer, 0, length);
        bytes_copied += length;
    }
    Log.d(TAG,
            "Finished copying Database " + DB_NAME +
                    " from the assets folder, to  " + dbpath +
                    String.valueOf(bytes_copied) + "were copied, in " +
                    String.valueOf(blocks_copied) + " blocks of size " +
                    String.valueOf(buffer_size) + "."
    );
    //Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
    Log.d(TAG,"All Streams have been flushed and closed.");
}

Results in :-

02-2110:24:31.8087972-7972/?D/VERSION:BuildVersionis2202-2110:24:31.8087972-7972/?D/DBPATH:DBPathis/data/data/so.cdfa/databases/db02-2110:24:31.8087972-7972/?D/DBPATH:DBPathis/data/data/so.cdfa/databases/db02-2110:24:31.8087972-7972/?D/COPYDATABASE:InitiatedCopyofthedatabasefiledbfromtheassetsfolder.02-2110:24:31.8087972-7972/?D/COPYDATABASE:Assetfiledbfoundsoattmeptingtocopyto/data/data/so.cdfa/databases/db02-2110:24:31.8087972-7972/?D/DBPATH:pathis/data/data/so.cdfa/databases/db02-2110:24:31.8097972-7972/?D/COPYDATABASE:Ateemptingcopyofblock1whichhas1024 bytes.02-2110:24:31.8097972-7972/?D/COPYDATABASE:Ateemptingcopyofblock2whichhas1024 bytes.02-2110:24:31.8097972-7972/?D/COPYDATABASE:Ateemptingcopyofblock3whichhas1024 bytes.02-2110:24:31.8097972-7972/?D/COPYDATABASE:Ateemptingcopyofblock4whichhas1024 bytes.02-2110:24:31.8097972-7972/?D/COPYDATABASE:Ateemptingcopyofblock5whichhas1024 bytes.02-2110:24:31.8097972-7972/?D/COPYDATABASE:Ateemptingcopyofblock6whichhas1024 bytes.02-2110:24:31.8097972-7972/?D/COPYDATABASE:Ateemptingcopyofblock7whichhas1024 bytes.02-2110:24:31.8097972-7972/?D/COPYDATABASE:Ateemptingcopyofblock8whichhas1024 bytes.02-2110:24:31.8097972-7972/?D/COPYDATABASE:Ateemptingcopyofblock9whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock10whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock11whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock12whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock13whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock14whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock15whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock16whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock17whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock18whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock19whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock20whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock21whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock22whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock23whichhas1024 bytes.02-2110:24:31.8107972-7972/?D/COPYDATABASE:Ateemptingcopyofblock24whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock25whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock26whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock27whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock28whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock29whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock30whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock31whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock32whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock33whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock34whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock35whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock36whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock37whichhas1024 bytes.02-2110:24:31.8117972-7972/?D/COPYDATABASE:Ateemptingcopyofblock38whichhas1024 bytes.02-2110:24:31.8127972-7972/?D/COPYDATABASE:Ateemptingcopyofblock39whichhas1024 bytes.02-2110:24:31.8127972-7972/?D/COPYDATABASE:Ateemptingcopyofblock40whichhas1024 bytes.02-2110:24:31.8127972-7972/?D/COPYDATABASE:FinishedcopyingDatabasedbfromtheassetsfolder,to/data/data/so.cdfa/databases/db40960werecopied,in40blocksofsize1024.02-2110:24:31.8127972-7972/?D/COPYDATABASE:AllStreamshavebeenflushedandclosed.

Entire DBHelper the above code was extracted from

  • Logs would be removed and many comments were commentary and fixing a problem i.e. the code could be cleaned up.

:-

publicclassDBHelperextendsSQLiteOpenHelper {

    privatestaticStringDB_NAME="db";
    private SQLiteDatabase myDataBase;
    privatefinal Context myContext;

    privateintbytes_copied=0;
    privatestaticintbuffer_size=1024;
    privateintblocks_copied=0;

    publicDBHelper(Context context) {
        super(context, DB_NAME, null, 1);

        this.myContext = context;
        // Check for and create (copy DB from assets) when constructing the DBHelperif (!checkDataBase()) {
            bytes_copied = 0;
            blocks_copied = 0;
            createDataBase();
        }
    }

    /**
     * Creates an empty database on the system and rewrites it with your own database.
     * */publicvoidcreateDataBase() {

        booleandbExist= checkDataBase(); // Double checkif(dbExist){
            //do nothing - database already exist
        } else {
            //By calling this method an empty database will be created into the default system path//of your application so we are gonna be able to overwrite that database with our database.//this.getReadableDatabase();//<<<<<<<<<< Dimsiss the above comment//By calling this method an empty database IS NOT created nor are the related -shm and -wal files//The method that creates the database is flawed and was only used to resolve the issue//of the copy failing in the absence of the databases directory.//The dbExist method, now utilised, checks for and creates the database directory, so there//is then no need to create the database just to create the databases library. As a result//the -shm and -wal files will not exist and thus result in the error associated with//Android 9+ failing with due to tables not existining after an apparently successful//copy.try {
                copyDataBase();
            } catch (IOException e) {
                Filedb=newFile(myContext.getDatabasePath(DB_NAME).getPath());
                if (db.exists()) {
                    db.delete();
                }
                e.printStackTrace();
                thrownewRuntimeException("Error copying database (see stack-trace above)");
            }
        }
    }

    /**
     * Check if the database already exist to avoid re-copying the file each time you open the application.
     * @return true if it exists, false if it doesn't
     */privatebooleancheckDataBase() {
        /**
         * Does not open the database instead checks to see if the file exists
         * also creates the databases directory if it does not exists
         * (the real reason why the database is opened, which appears to result in issues)
         */Filedb=newFile(myContext.getDatabasePath(DB_NAME).getPath()); //Get the file name of the database
        Log.d("DBPATH","DB Path is " + db.getPath());
        if (db.exists()) returntrue; // If it exists then return doing nothing// Get the parent (directory in which the database file would be)Filedbdir= db.getParentFile();
        // If the directory does not exits then make the directory (and higher level directories)/*
        if (!dbdir.exists()) {
            db.getParentFile().mkdirs();
            dbdir.mkdirs();
        }
        */returnfalse;
    }

    /**
     * Copies your database from your local assets-folder to the just created empty database in the
     * system folder, from where it can be accessed and handled.
     * This is done by transfering bytestream.
     * */privatevoidcopyDataBase()throws IOException {

        finalStringTAG="COPYDATABASE";

        //Open your local db as the input stream
        Log.d(TAG,"Initiated Copy of the database file " + DB_NAME + " from the assets folder.");
        InputStreammyInput= myContext.getAssets().open(DB_NAME); // Open the Asset fileStringdbpath= myContext.getDatabasePath(DB_NAME).getPath();
        Log.d(TAG,"Asset file " + DB_NAME + " found so attmepting to copy to " + dbpath);

        // Path to the just created empty db//String outFileName = DB_PATH + DB_NAME;//Open the empty db as the output streamFileoutfile=newFile(myContext.getDatabasePath(DB_NAME).toString());
        Log.d("DBPATH","path is " + outfile.getPath());
        //outfile.setWritable(true); // NOT NEEDED as permission already applies//OutputStream myoutputx2 = new FileOutputStream(outfile);/* Note done in checkDatabase method
        if (!outfile.getParentFile().exists()) {
            outfile.getParentFile().mkdirs();
        }
        */OutputStreammyOutput=newFileOutputStream(outfile);
        //transfer bytes from the inputfile to the outputfilebyte[] buffer = newbyte[buffer_size];
        int length;
        while ((length = myInput.read(buffer))>0) {
            blocks_copied++;
            Log.d(TAG,"Ateempting copy of block " + String.valueOf(blocks_copied) + " which has " + String.valueOf(length) + " bytes.");
            myOutput.write(buffer, 0, length);
            bytes_copied += length;
        }
        Log.d(TAG,
                "Finished copying Database " + DB_NAME +
                        " from the assets folder, to  " + dbpath +
                        String.valueOf(bytes_copied) + "were copied, in " +
                        String.valueOf(blocks_copied) + " blocks of size " +
                        String.valueOf(buffer_size) + "."
        );
        //Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
        Log.d(TAG,"All Streams have been flushed and closed.");
    }


    @Overridepublicsynchronizedvoidclose() {
        if(myDataBase != null)
            myDataBase.close();
        super.close();
    }

    @OverridepublicvoidonCreate(SQLiteDatabase db) {
    }

    @OverridepublicvoidonUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }

    @OverridepublicvoidonConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
        Log.d("DBCONFIGURE","Database has been configured ");
    }

    @OverridepublicvoidonOpen(SQLiteDatabase db) {
        super.onOpen(db);
        Log.d("DBOPENED","Database has been opened.");
    }
}  

Solution 2:

The error says it could not find the output file. Hence you need to create one first in order to open that and copy from the asset.

try {       
    StringDB_PATH="/data/data/" + "your.application.package.name" + "/databases/";
    Filedir=newFile(DB_PATH);
    if (!dir.exists()) dir.mkdir();
    Filef=newFile(DB_PATH + DB_NAME);
    if (!f.exists()) {
        f.createNewFile();
    }
} catch (Exception e) {
    e.printStackTrace();
}

// Then it should workOutputStreammOutput=newFileOutputStream(f);

Post a Comment for "Having Trouble Copying An Existing Sqlite Db File From Assets To Android Project"