简体   繁体   中英

Copy from assets folder fails

I have studied various tutorials and postings on stackoverflow but I still stuck on this issue. I have been working on it for weeks.

When I find why it is not working, I will write a clear and comprehensive tutorial for the benefit of all.

  1. I have simple SQLite database stored in the Assets folder of the project
  2. As this is just a test to aid learning, the main activity does only one thing: to create an instance of DBHelper and thereby run CopyDbIfNotExists()
  3. Device File Explorer shows that a directory "databases" is created in the /data/data/com.mo.shipdatabase3 directory, but this directory is empty - there is no database.
  4. Logcat logs the diagnostic message from throw new Error("Error copying database: " + e.getMessage()); indicating the copy has failed.

I don't know why the copy is failing. I have been working on it for weeks. I have also studied and tried other tutorials - I understand them - I think but I don't know why it fails.

package com.mo.shipdatabase3;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

public class DBHelper extends SQLiteOpenHelper {

    public static ArrayList<Customer> arrayList= new ArrayList<>();

    private static final String dbName = "Customers.db";
    private static final int dbVersion = 1;
    private Context context;

    public DBHelper(Context context) {
        super(context, dbName, null, dbVersion);
        this.context = context;

        this.copyDbIfNotExists();

    }

    private void copyDbIfNotExists() {
        // Ensure /data/data/YOUR_PACKAGE_NAME/databases/directory is created and therefore exists
        File dbDir = new File(context.getDatabasePath(dbName).getParentFile().getPath());
        if (!dbDir.exists()) { // which it won't when first run
            dbDir.mkdir();
        }

        // copy database starts here
        String appDbPath = this.context.getDatabasePath(dbName).getAbsolutePath();
        File dbFile = new File(appDbPath);
        if (!dbFile.exists()) { // which is won't when first run, only the directory will exist
            try {
                InputStream mInput = context.getAssets().open("Customers.db");
                OutputStream mOutput = new FileOutputStream(appDbPath);
                byte[] mBuffer = new byte[1024];
                int mLength;
                while ((mLength = mInput.read(mBuffer, 0, 1024)) > 0)
                    mOutput.write(mBuffer, 0, mLength);
                mOutput.flush();
                mInput.close();

            } catch (IOException e) {
                throw new Error("Error copying database: " + e.getMessage());
            }
        }
    }

    @Override
    public void onCreate(SQLiteDatabase dB) {
        // Nothing to do. Use existing database

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        // Upgrade

    }

}

Try this snippet, I used it before in my project.

private fun copyDBFromStorage(databaseName: String) {
    if (checkIfDBExists(this, databaseName)) return
    val databaseFile = File(this.getDatabasePath(databaseName).toString())
    val sourceLocation = assets.open("database/fakedb.sql")
    try {
        val inputStream = sourceLocation
        val os = FileOutputStream(databaseFile)
        val buffer = ByteArray(1024 * 32)
        var length = inputStream.read(buffer)
        while (length > 0) {
            os.write(buffer, 0, length)
            length = inputStream.read(buffer)
        }
        os.flush()
        os.close()
        inputStream.close()

    } catch (ex: IOException) {
        ex.printStackTrace();
        throw  RuntimeException("Error copying storage database");
    }
}


private fun checkIfDBExists(
    context: Context,
    databaseName: String
): Boolean {
    val dbfile = File(context.getDatabasePath(databaseName).toString())
    if (dbfile.exists()) return true
    if (!dbfile.parentFile.exists()) {
        dbfile.parentFile.mkdirs()
    }
    return false
}

You can test it by checking if the database is exist or not,

copyDBFromStorage("fakedb.sql")
    val file = getDatabasePath("fakedb.sql").isFile
    Log.d("MainActivity", "onCreate: $file")

In this case, you should get True in the log.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM