简体   繁体   English

从资产文件夹复制失败

[英]Copy from assets folder fails

I have studied various tutorials and postings on stackoverflow but I still stuck on this issue.我已经研究了关于 stackoverflow 的各种教程和帖子,但我仍然坚持这个问题。 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我有简单的 SQLite 数据库存储在项目的资产文件夹中
  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()由于这只是一个辅助学习的测试,主要活动只做一件事:创建DBHelper的实例并运行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. Device File Explorer 显示在 /data/data/com.mo.shipdatabase3 目录中创建了一个目录“databases”,但是这个目录是空的——没有数据库。
  4. Logcat logs the diagnostic message from throw new Error("Error copying database: " + e.getMessage()); Logcat 记录来自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.在这种情况下,您应该在日志中获得True

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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