资产文件夹中的SQLite在运行时生成异常

时间:2018-04-14 09:06:42

标签: android sqlite android-sqlite sqliteopenhelper

我在尝试在android中加载我的数据库文件时遇到异常:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.example.jk.sqlite_test, PID: 32660
              java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.jk.sqlite_test/com.example.jk.sqlite_test.MainActivity}: com.readystatesoftware.sqliteasset.SQLiteAssetHelper$SQLiteAssetException: Missing databases/Data.db file (or .zip, .gz archive) in assets, or target folder not writable
                  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2493)
                  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2576)
                  at android.app.ActivityThread.access$1000(ActivityThread.java:155)
                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)
                  at android.os.Handler.dispatchMessage(Handler.java:102)
                  at android.os.Looper.loop(Looper.java:148)
                  at android.app.ActivityThread.main(ActivityThread.java:5539)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
               Caused by: com.readystatesoftware.sqliteasset.SQLiteAssetHelper$SQLiteAssetException: Missing databases/Data.db file (or .zip, .gz archive) in assets, or target folder not writable
                  at android.content.res.AssetManager.openAsset(Native Method)
                  at android.content.res.AssetManager.open(AssetManager.java:313)
                  at android.content.res.AssetManager.open(AssetManager.java:287)
                  at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.copyDatabaseFromAssets(SQLiteAssetHelper.java:436)
                  at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.createOrOpenDatabase(SQLiteAssetHelper.java:400)
                  at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getWritableDatabase(SQLiteAssetHelper.java:176)
                  at com.example.jk.sqlite_test.DatabaseAccess.open(DatabaseAccess.java:28)
                  at com.example.jk.sqlite_test.MainActivity.onCreate(MainActivity.java:25)
                  at android.app.Activity.performCreate(Activity.java:6289)
                  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2446)
                  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2576) 
                  at android.app.ActivityThread.access$1000(ActivityThread.java:155) 
                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) 
                  at android.os.Handler.dispatchMessage(Handler.java:102) 
                  at android.os.Looper.loop(Looper.java:148) 
                  at android.app.ActivityThread.main(ActivityThread.java:5539) 
                  at java.lang.reflect.Method.invoke(Native Method) 
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
D/AppTracker: App Event: crash

以下是我的代码:

package com.example.jk.sqlite_test;

import android.content.Context;
import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;

public class DatabaseOpenHelper extends SQLiteAssetHelper {

    private static final String DATABASE_NAME = "Data.db";
    private static final int DATABASE_VERSION = 3;

     public DatabaseOpenHelper(Context context) {
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
}

而且,

package com.example.jk.sqlite_test;

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

import java.util.ArrayList;

public class DatabaseAccess {

    private SQLiteOpenHelper openHelper;
    private SQLiteDatabase database;
    private static DatabaseAccess instance;

    private DatabaseAccess(Context context) {
        this.openHelper = new DatabaseOpenHelper(context);
    }

    public static DatabaseAccess getInstance(Context context) {
        if (instance == null) {
            instance = new DatabaseAccess(context);
        }
        return instance;
    }   

    public void open() {
        this.database = openHelper.getWritableDatabase();
    }

    public void close() {
        if (database != null) {
            this.database.close();
        }
    }

    public String getAll()
    { 
         String str = "";

         Cursor cursor = database.rawQuery("SELECT * FROM pdata" , null);

         cursor.moveToFirst();

        while(!cursor.isAfterLast())
        {
             str += cursor.getString(1) + "\t" + cursor.getString(2) + "\t" + cursor.getString(3) + "\n";
        }
        return str;
    }
}

我想我正在使用SQLite 3数据库,因此我将版本保留为3。

在SQLite Studio中创建数据库文件后,我没有获得数据库文件的任何文件扩展名,所以我将扩展名保留为db,正如许多相同类型问题的答案中所建议的那样。

我也尝试使用不同的版本值和扩展名,例如.sqlite / .sqlite3,但它没有解决问题。

请帮忙! 谢谢。

3 个答案:

答案 0 :(得分:0)

您正尝试在处于只读模式(资产)的文件夹中以写入模式打开数据库。

尝试使用openHelper.getReadableDatabase()以只读模式打开数据库。

答案 1 :(得分:0)

SQLiteOpenHelper 要求文件(扩展名与文件名不相关,扩展名必须与数据库名称相同)才能在< strong> assets/databases 文件夹/目录不在 assets 文件夹/目录中。因此,您必须 /assets/databases/Data.db

如果 databases 文件夹中不存在 assets 文件夹,则创建该文件夹,然后将Data.db文件复制到数据库文件夹。

其他

仔细查看您的代码,如果您使用getAll方法,则会进入无限循环,并且movetoFirst至少有一行,但不要{{1}在while循环中。

我建议moveToNext方法应该是: -

getAll

答案 2 :(得分:0)

        public class DatabaseHelper extends SQLiteOpenHelper {

            private static String DB_NAME = "baseProject.db";
            private static String DB_PATH = "";
            private static final int DB_VERSION = 3;

     public DatabaseHelper(Context context) {
            super(context, DB_NAME, null, DB_VERSION);
            if (android.os.Build.VERSION.SDK_INT >= 17)
                DB_PATH = context.getApplicationInfo().dataDir + /databases/";
            else
                DB_PATH = "/data/data/" + context.getPackageName() + 
                    "/databases/";
            this.mContext = context;

            copyDataBase();

            this.getReadableDatabase();
        }


    private boolean checkDataBase() {
            File dbFile = new File(DB_PATH + DB_NAME);
            return dbFile.exists();
        }

        private void copyDataBase() {
            if (!checkDataBase()) {
                this.getReadableDatabase();
                this.close();
                try {
                    copyDBFile();
                } catch (IOException mIOException) {
                    throw new Error("ErrorCopyingDataBase");
                }
            }
        }

        private void copyDBFile() throws IOException {
            InputStream mInput = mContext.getAssets().open(DB_NAME);

            OutputStream mOutput = new FileOutputStream(DB_PATH + DB_NAME);
            byte[] mBuffer = new byte[1024];
            int mLength;
            while ((mLength = mInput.read(mBuffer)) > 0)
                mOutput.write(mBuffer, 0, mLength);
            mOutput.flush();
            mOutput.close();
            mInput.close();
        }

     @Override
        public synchronized void close() {
            if (mDataBase != null)
                mDataBase.close();
            super.close();
        }

        @Override
        public void onCreate(SQLiteDatabase db) {

        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            if (newVersion > oldVersion)
                mNeedUpdate = true;
        }

}

尝试以上课程