从资产复制时数据库已损坏

时间:2012-07-08 16:10:15

标签: android sqlite android-assets

我有一个信息数据库,我试图从资产复制到设备上的应用程序的数据库目录中。 我从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

1 个答案:

答案 0 :(得分: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