2016-07-14 69 views
0

我有一個sqlite數據庫存儲在assets/databases/minitest.db,我試圖將它從assets文件夾複製到本地文件系統,然後打開它。表sqlite中的數據庫丟失的表

當我打開它,我得到一個表未找到異常。

我很確定它沒有錯誤的數據庫本身,因爲當我用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 
+0

如果您嘗試使用Android的'sqlite3'命令行打開'.db'文件,會發生什麼? –

+0

我可能是錯的..但我相信onUpgrade失敗。你可以調用:opendatabase()來打開數據庫。這會導致onUpgrade(),它會嘗試從資產文件夾中複製。但是,由於您的數據庫已打開,因此無法以這種方式編寫,您的應用程序正在保留舊數據庫。 – W0rmH0le

+0

是否有一張名爲「Trigrams?」的表,拼寫是否正確? –

回答

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; 
    } 
} 
+0

這固定了它。謝謝 :) – user1762507