sqlite

时间:2016-07-14 20:40:57

标签: android sqlite android-sqlite

我有一个存储在assets/databases/minitest.db中的sqlite数据库,我尝试将其从assets文件夹复制到本地文件系统,然后打开它。

当我打开它时,我得到一个未找到的表异常。

我很确定数据库本身没有问题,因为当我用sqlite查看器打开它时,它看起来很好。我现在一直在谷歌搜索这个问题大约2个小时,我看到了一些类似的问题,但他们的解决方案似乎都没有用,所以我真的不知道该怎么做。

代码:

mydatabase = new DataBaseHelper(c).myDataBase;
Cursor mCursor = mydatabase.rawQuery("SELECT third FROM Trigrams WHERE first='" + first.toLowerCase() + "' AND second ='" + second.toLowerCase() + "' ORDER BY freq DESC LIMIT 0,3", null);

完成DataBaseHelper:

class DataBaseHelper extends SQLiteOpenHelper {
    private Context mycontext;
    private static final String DB_NAME = "minitest.db";    
    private static final String DB_PATH = "/data/data/" +       BuildConfig.APPLICATION_ID + "/databases/";
    private static final int DB_VERSION = 3;
    public SQLiteDatabase myDataBase;

    public DataBaseHelper(Context context) throws IOException {
        super(context, DB_NAME, null, DB_VERSION);
        this.mycontext = context;
        boolean dbexist = checkdatabase();
        if (dbexist) {
            System.out.println("Database exists");
            opendatabase();
        } else {
            System.out.println("Database doesn't exist");
            createdatabase();
            opendatabase();
        }
    }

    public void createdatabase() throws IOException {
        boolean dbexist = checkdatabase();
        if (dbexist) {
            System.out.println(" Database exists.");
        } else {
            this.getReadableDatabase();
            try {
                copydatabase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }
    }

    private boolean checkdatabase() {

        boolean checkdb = false;
        try {
            String myPath = DB_PATH + DB_NAME;
            File dbfile = new File(myPath);
            checkdb = dbfile.exists();
        } catch (SQLiteException e) {
            System.out.println("Database doesn't exist");
        }
        return checkdb;
    }

    private void copydatabase() throws IOException {
        //Open your local db as the input stream
        InputStream myinput = mycontext.getAssets().open("databases/" + DB_NAME);

        // Path to the just created empty db
        String outfilename = DB_PATH + DB_NAME;

        //Open the empty db as the output stream
        OutputStream myoutput = new FileOutputStream(outfilename);

        // transfer byte to inputfile to outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myinput.read(buffer)) > 0) {
            myoutput.write(buffer, 0, length);
        }

        //Close the streams
        myoutput.flush();
        myoutput.close();
        myinput.close();
    }

    public void opendatabase() throws SQLException {
        //Open the database
        String mypath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(mypath, null, SQLiteDatabase.OPEN_READONLY);
    }

    public synchronized void close() {
        if (myDataBase != null) {
            myDataBase.close();
        }
        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (newVersion > oldVersion)
            try {
                copydatabase();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
}

错误日志:

E/SQLiteLog: (1) no such table: Trigrams
E/InputEventReceiver: Exception dispatching input event.
E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback
E/MessageQueue-JNI: android.database.sqlite.SQLiteException: no such table: Trigrams (code 1): , while compiling: SELECT third FROM Trigrams WHERE first='a' AND second ='baby' ORDER BY freq DESC LIMIT 0,3
    at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
    at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
    at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
    at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
    at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
    at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
    at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1355)
    at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1294)
    at com.chair49.sentimentkeyboard.analysis.NextWord.getNextWords(NextWord.java:38)
    at com.chair49.sentimentkeyboard.SimpleIME.onKey(SimpleIME.java:125)
    at android.inputmethodservice.KeyboardView.detectAndSendKey(KeyboardView.java:828)
    at android.inputmethodservice.KeyboardView.repeatKey(KeyboardView.java:1371)
    at android.inputmethodservice.KeyboardView.onModifiedTouchEvent(KeyboardView.java:1281)
    at android.inputmethodservice.KeyboardView.onTouchEvent(KeyboardView.java:1214)
    at android.view.View.dispatchTouchEvent(View.java:9337)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2198)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2198)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2198)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2198)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2198)
    at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2432)
    at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1746)
    at android.app.Dialog.dispatchTouchEvent(Dialog.java:787)
    at android.inputmethodservice.SoftInputWindow.dispatchTouchEvent(SoftInputWindow.java:93)
    at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2393)
    at android.view.View.dispatchPointerEvent(View.java:9557)
    at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4263)
    at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4102)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3644)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3697)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3663)
    at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3789)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3671)
    at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3846)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3644)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3697)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3663)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3671)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3644)
    at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5955)
    at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5929)
    at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5890)
    at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6058)
    at android.view.InputEventReceiver.dispatchInputEvent(Inp
07-14 14:12:42.161 14083-14083/com.chair49.sentimentkeyboard E/AndroidRuntime: FATAL EXCEPTION: main

1 个答案:

答案 0 :(得分:0)

我相信您的数据库没有更新。我在asset文件夹中遇到类似数据库的问题。

onUpdate期间的工作流程

更新数据库(已存在)时,将调用以下方法:

opendatabase()->SQLiteDatabase.openDatabase()

这将打开您的数据库,并且还会触发onUpgrade()

onUpgrade()中,您可以尝试:

onUpgrade()->copydatabase()

但是,数据库已打开,您将无法覆盖文件minitest.db

这将导致IOException并且数据库未更新。

您没有看到该异常,因为您正在处理IOException

如何确认

您可以卸载/安装(或只删除数据)您的应用。如果工作正常,似乎数据库已更正,但在某些更新期间,您的表未更新失败。

您还可以将数据库编号更新为4并检查日志消息并确认onUpgrade()失败。

解决方法

我就是这样做的:

class DataBaseHelper extends SQLiteOpenHelper {
    private boolean shouldBeUpdated;

    public DataBaseHelper(Context context) throws IOException {
        ...
        shouldBeUpdated = false;

        if (dbexist) {
            System.out.println("Database exists");
            opendatabase();
        } else {
            System.out.println("Database doesn't exist");
            createdatabase();
            opendatabase();
        }
    }

    public void opendatabase() throws SQLException {
        String mypath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(mypath, null, SQLiteDatabase.OPEN_READONLY);

        // CLOSE DATABASE BEFORE UPDATING IT
        close();

        if(shouldBeUpdated) {
            try {
                copydatabase();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

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