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
4

1 回答 1

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
于 2012-07-08T16:45:50.087 回答