2012-07-08 53 views
2

我有一個信息數據庫,我試圖從資產複製到設備上應用程序的數據庫目錄中。 我已從1獲取代碼,但將複製代碼移入DatabaseHelper類的onCreate方法(因爲它調用它)。 數據庫沒有錯誤地複製,但當我嘗試從數據庫訪問數據時,我得到一個SQLiteException拋出,表示該表不存在。當我在計算機上打開新創建的數據庫文件時,我可以看到它的大小正確,但不包含除'android_metadata'之外的任何表格。如果我手動將未損壞的數據庫文件從我的電腦複製到應用程序的數據庫目錄中,那麼它的功能正常,但顯然我不能這樣做。從資產複製時數據庫被損壞

這裏是我用來打開數據庫的代碼:

public ReferenceDatabaseAdapter open() throws SQLException { 
     mDbHelper = new DatabaseHelper(mCtx); 
     mDb = mDbHelper.getReadableDatabase(); 
     return this; 
    } 

這裏是onCreate方法:

 public void onCreate(SQLiteDatabase db) 
     { 
      Log.d("AutoBagger","onCreate called for reference database"); 
      //Open your local db as the input stream 
      InputStream assetsDbFile; 
      try { 
       assetsDbFile = dHCtx.getAssets().open("reference.sqlite"); 
       // Path to the just created empty db 
       String dbFile = "/data/data/" + dHCtx.getPackageName() + "/databases/"+DATABASE_NAME; 

       //Open the empty db as the output stream 
       OutputStream outputStream = new FileOutputStream(dbFile); 

       //transfer bytes from the assetsDbFile to the dbFile 
       byte[] buffer = new byte[1024]; 
       int length; 
       while ((length = assetsDbFile.read(buffer))>0){ 
       outputStream.write(buffer, 0, length); 
       } 

       //Close the streams 
       outputStream.flush(); 
       outputStream.close(); 
       assetsDbFile.close(); 
       Log.d("AutoBagger","No errors whilst copying database"); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       Log.d("AutoBagger","IOException encountered when copying database from assets"); 
      } 
     } 

在第一次運行我只是得到關於不存在表中的錯誤,但當我再次運行它(當數據庫已被複制)時,我得到一個SQLiteDatabaseCorruptionException「數據庫磁盤映像格式不正確」。 任何想法,我要錯了嗎?謝謝。

logcat的輸出,當數據庫尚未複製:

>07-08 17:16:41.490: D/AutoBagger(5145): DatabaseHelper constructor called (finished) 
>07-08 17:16:41.530: D/AutoBagger(5145): onCreate called for reference database 
>07-08 17:16:41.550: D/AutoBagger(5145): No errors whilst copying database 
>07-08 17:16:41.550: D/AutoBagger(5145): fetchRows called 
>07-08 17:16:41.550: I/Database(5145): sqlite returned: error code = 1, msg = no such table: hills 
>07-08 17:16:41.550: D/AndroidRuntime(5145): Shutting down VM 
>07-08 17:16:41.550: W/dalvikvm(5145): threadid=1: thread exiting with uncaught exception (group=0x402a7560) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): FATAL EXCEPTION: main 
>07-08 17:16:41.570: E/AndroidRuntime(5145): android.database.sqlite.SQLiteException: no such table: hills: , while compiling: SELECT classification FROM hills WHERE dobihId = 1 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:92) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:65) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:83) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:49) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:42) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1356) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1235) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1189) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1271) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at com.s0812532.AutoBagger.ReferenceDatabaseAdapter.fetchRows(ReferenceDatabaseAdapter.java:196) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at com.s0812532.AutoBagger.Hill.isMunro(Hill.java:172) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at com.s0812532.AutoBagger.TestLauncher$12.onClick(TestLauncher.java:157) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.view.View.performClick(View.java:2501) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.view.View$PerformClick.run(View.java:9107) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.os.Handler.handleCallback(Handler.java:587) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.os.Handler.dispatchMessage(Handler.java:92) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.os.Looper.loop(Looper.java:130) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at android.app.ActivityThread.main(ActivityThread.java:3835) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at java.lang.reflect.Method.invokeNative(Native Method) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at java.lang.reflect.Method.invoke(Method.java:507) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605) 
>07-08 17:16:41.570: E/AndroidRuntime(5145): at dalvik.system.NativeStart.main(Native Method) 
>07-08 17:16:43.181: I/Process(5145): Sending signal. PID: 5145 SIG: 9 

logcat的輸出,當數據庫已被複制:

>07-08 17:11:43.669: D/AutoBagger(5136): DatabaseHelper constructor called (finished) 
>07-08 17:11:43.669: I/Database(5136): sqlite returned: error code = 11, msg = database corruption at line 46139 of [42537b6056] 
>07-08 17:11:43.669: I/Database(5136): sqlite returned: error code = 11, msg = statement aborts at 5: [SELECT locale FROM android_metadata LIMIT 1] 
>07-08 17:11:43.669: E/Database(5136): SELECT locale FROM android_metadata failed 
>07-08 17:11:43.679: E/Database(5136): Failed to setLocale() when constructing, closing the database 
>07-08 17:11:43.679: E/Database(5136): android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed 
>07-08 17:11:43.679: E/Database(5136): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method) 
>07-08 17:11:43.679: E/Database(5136): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1987) 
>07-08 17:11:43.679: E/Database(5136): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1855) 
>07-08 17:11:43.679: E/Database(5136): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820) 
>07-08 17:11:43.679: E/Database(5136): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854) 
>07-08 17:11:43.679: E/Database(5136): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:847) 
>07-08 17:11:43.679: E/Database(5136): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:572) 
>07-08 17:11:43.679: E/Database(5136): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203) 
>07-08 17:11:43.679: E/Database(5136): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:118) 
>07-08 17:11:43.679: E/Database(5136): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187) 
>07-08 17:11:43.679: E/Database(5136): at com.s0812532.AutoBagger.ReferenceDatabaseAdapter.open(ReferenceDatabaseAdapter.java:145) 
>07-08 17:11:43.679: E/Database(5136): at com.s0812532.AutoBagger.Hill.<init>(Hill.java:55) 
>07-08 17:11:43.679: E/Database(5136): at com.s0812532.AutoBagger.TestLauncher$12.onClick(TestLauncher.java:156) 
>07-08 17:11:43.679: E/Database(5136): at android.view.View.performClick(View.java:2501) 
>07-08 17:11:43.679: E/Database(5136): at android.view.View$PerformClick.run(View.java:9107) 
>07-08 17:11:43.679: E/Database(5136): at android.os.Handler.handleCallback(Handler.java:587) 
>07-08 17:11:43.679: E/Database(5136): at android.os.Handler.dispatchMessage(Handler.java:92) 
>07-08 17:11:43.679: E/Database(5136): at android.os.Looper.loop(Looper.java:130) 
>07-08 17:11:43.679: E/Database(5136): at android.app.ActivityThread.main(ActivityThread.java:3835) 
>07-08 17:11:43.679: E/Database(5136): at java.lang.reflect.Method.invokeNative(Native Method) 
>07-08 17:11:43.679: E/Database(5136): at java.lang.reflect.Method.invoke(Method.java:507) 
>07-08 17:11:43.679: E/Database(5136): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847) 
>07-08 17:11:43.679: E/Database(5136): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605) 
>07-08 17:11:43.679: E/Database(5136): at dalvik.system.NativeStart.main(Native Method) 
>07-08 17:11:43.689: E/Database(5136): Deleting and re-creating corrupt database /data/data/com.s0812532.AutoBagger/databases/reference.sqlite 
>07-08 17:11:43.689: E/Database(5136): android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed 
>07-08 17:11:43.689: E/Database(5136): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method) 
>07-08 17:11:43.689: E/Database(5136): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1987) 
>07-08 17:11:43.689: E/Database(5136): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1855) 
>07-08 17:11:43.689: E/Database(5136): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820) 
>07-08 17:11:43.689: E/Database(5136): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854) 
>07-08 17:11:43.689: E/Database(5136): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:847) 
>07-08 17:11:43.689: E/Database(5136): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:572) 
>07-08 17:11:43.689: E/Database(5136): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203) 
>07-08 17:11:43.689: E/Database(5136): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:118) 
>07-08 17:11:43.689: E/Database(5136): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187) 
>07-08 17:11:43.689: E/Database(5136): at com.s0812532.AutoBagger.ReferenceDatabaseAdapter.open(ReferenceDatabaseAdapter.java:145) 
>07-08 17:11:43.689: E/Database(5136): at com.s0812532.AutoBagger.Hill.<init>(Hill.java:55) 
>07-08 17:11:43.689: E/Database(5136): at com.s0812532.AutoBagger.TestLauncher$12.onClick(TestLauncher.java:156) 
>07-08 17:11:43.689: E/Database(5136): at android.view.View.performClick(View.java:2501) 
>07-08 17:11:43.689: E/Database(5136): at android.view.View$PerformClick.run(View.java:9107) 
>07-08 17:11:43.689: E/Database(5136): at android.os.Handler.handleCallback(Handler.java:587) 
>07-08 17:11:43.689: E/Database(5136): at android.os.Handler.dispatchMessage(Handler.java:92) 
>07-08 17:11:43.689: E/Database(5136): at android.os.Looper.loop(Looper.java:130) 
>07-08 17:11:43.689: E/Database(5136): at android.app.ActivityThread.main(ActivityThread.java:3835) 
>07-08 17:11:43.689: E/Database(5136): at java.lang.reflect.Method.invokeNative(Native Method) 
>07-08 17:11:43.689: E/Database(5136): at java.lang.reflect.Method.invoke(Method.java:507) 
>07-08 17:11:43.689: E/Database(5136): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847) 
>07-08 17:11:43.689: E/Database(5136): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605) 
>07-08 17:11:43.689: E/Database(5136): at dalvik.system.NativeStart.main(Native Method) 
>07-08 17:11:43.709: D/AutoBagger(5136): onCreate called for reference database 
>07-08 17:11:43.719: D/AutoBagger(5136): No errors whilst copying database 
>07-08 17:11:43.729: D/AutoBagger(5136): fetchRows called 
>07-08 17:11:43.729: I/Database(5136): sqlite returned: error code = 1, msg = no such table: hills 
>07-08 17:11:43.729: D/AndroidRuntime(5136): Shutting down VM 
>07-08 17:11:43.729: W/dalvikvm(5136): threadid=1: thread exiting with uncaught exception (group=0x402a7560) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): FATAL EXCEPTION: main 
>07-08 17:11:43.739: E/AndroidRuntime(5136): android.database.sqlite.SQLiteException: no such table: hills: , while compiling: SELECT classification FROM hills WHERE dobihId = 1 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:92) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:65) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:83) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:49) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:42) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1356) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1235) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1189) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1271) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at com.s0812532.AutoBagger.ReferenceDatabaseAdapter.fetchRows(ReferenceDatabaseAdapter.java:196) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at com.s0812532.AutoBagger.Hill.isMunro(Hill.java:172) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at com.s0812532.AutoBagger.TestLauncher$12.onClick(TestLauncher.java:157) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.view.View.performClick(View.java:2501) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.view.View$PerformClick.run(View.java:9107) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.os.Handler.handleCallback(Handler.java:587) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.os.Handler.dispatchMessage(Handler.java:92) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.os.Looper.loop(Looper.java:130) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at android.app.ActivityThread.main(ActivityThread.java:3835) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at java.lang.reflect.Method.invokeNative(Native Method) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at java.lang.reflect.Method.invoke(Method.java:507) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605) 
>07-08 17:11:43.739: E/AndroidRuntime(5136): at dalvik.system.NativeStart.main(Native Method) 
>07-08 17:11:45.461: I/Process(5136): Sending signal. PID: 5136 SIG: 9 
+0

試試這裏的代碼:http://stackoverflow.com/questions/9109438/using-already-created-database-with-android/9109728#9109728 – 2012-07-08 16:30:05

+0

當你的錯誤..那麼C失去了應用程序..並再次運行..如果它運行,然後我會告訴你的問題 – 2012-07-08 16:40:00

+0

第二次,它不會正常運行,因爲當檢測到損壞的數據庫時,它刪除它,並重新創建爲空白,所以正確的表不存在,並且你得到相關的錯誤。 – ablack89 2012-07-08 19:09:07

回答

0

嘗試這種模式:

public class DatabaseHelper extends SQLiteOpenHelper{ 
    private static String PKG_NAME = "name_of_package_for_apk"; 
    private static String DB_PATH = "/data/data/" + PKG_NAME + "/databases/"; 
    private static String DB_NAME = "db.db3"; 

    private SQLiteDatabase myDataBase; 
    private final Context myContext; 
    DatabaseHelper(Context context) 
    { 
     super(context, DB_NAME, null, 1); 
     this.myContext = context; 
    } 
    @Override 
    public void onCreate(SQLiteDatabase db) { } 
    public void createDataBase() throws IOException{ 
     boolean dbExist = checkDataBase(); 
     if (!dbExist){ 
      getReadableDatabase(); 
      copyDatabase(); 
     }else{ 
      this.close(); 
     } 
    } 

    private boolean checkDataBase(){ 
     SQLiteDatabase checkDB = null; 
     try{ 
      String myPath = DB_PATH + DB_NAME; 
      checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY|SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
     }catch(SQLiteException e){ 
      //database does't exist yet. 
      Log.v(TAG, "[checkDataBase] - Database does not exist... YET!"); 
     }finally{ 
      if(checkDB != null) checkDB.close(); 
     } 
     return (checkDB != null) ? true : false; 
    } 
    private void copyDataBase() throws IOException{ 
     boolean bCopyOk = false; 
     try{ 
      //Open your local db as the input stream 
      InputStream myInput = myContext.getAssets().open(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 bytes from the inputfile to the 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(); 
      bCopyOk = true; 
     }catch(Exception ex){ 
     }finally{ 
      if (bCopyOk) Log.v(TAG, "[copyDataBase] - Database copied OK!"); 
     } 
    } 
    @SuppressWarnings("unused") 
    public void openDataBase() throws SQLException{ 
     //Open the database 
     String myPath = DB_PATH + DB_NAME; 
     myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 
    } 
    @Override 
    public synchronized void close() { 
     if(myDataBase != null) myDataBase.close(); 
     super.close(); 
    } 
} 

簡單地說,做到這一點:

dbHelper = new DatabaseHelper(getApplicationContext()); 
dbHelper.createDatabase(); 

編輯:它蒸發元數據丟失這個重要的入口,通過Sqliteman的GUI前端,使用該腳本

CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US') 

線索是在logcat的本身:

>07-08 17:11:43.669: E/Database(5136): SELECT locale FROM android_metadata failed 
>07-08 17:11:43.679: E/Database(5136): Failed to setLocale() when constructing, closing the database 
>07-08 17:11:43.679: E/Database(5136): android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed 
+0

感謝您的回答,但我已更改我的代碼以適應您提供的模式,但數據庫仍然被損壞,並且在數據庫本身的複製過程中沒有發生錯誤。還有什麼可以的嗎?謝謝。 – ablack89 2012-07-08 19:07:26

+0

已編輯我的答案:) – t0mm13b 2012-07-08 19:16:23

+0

我正在複製的數據庫已經有一個'android_metadata'表(它在手動複製時工作正常),所以我認爲這部分日誌只是因爲第一件事系統試圖從數據庫查詢元數據,這是錯誤中提到的唯一原因? – ablack89 2012-07-08 19:40:41