SQLiteDatabaseCorruptException:数据库磁盘映像损坏。

3
我在这个程序中遇到了困难。我已经在互联网上搜索了解决此问题的方法,但是一直没有找到。 我正在尝试从远程服务器下载SQLite数据库。 它似乎下载得很好,我可以将文件从手机上取出并查看它。 它看起来很正常。 但是,当我的程序尝试读取数据库时,我会得到以下错误信息:
android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed

我在服务器上删除了数据库和手机上的数据库,并跳转到创建数据库并将其提交到服务器的活动。它做得很好,现在数据库已经在手机和服务器上重新创建,我可以打开它们并查看它们。

我重新启动程序,我的Spinner未填充数据,我仍然得到同样的错误。

以下是填充Spinner的代码:

    private void fillSpinner(){
    mDbHelper = new myDbAdapter(this);
    mDbHelper.open();
    Cursor c = mDbHelper.fetchColumns(new String[] {"_id","name"});

    if ( ! c.moveToFirst() ){

        mDbHelper.createRow("Create Name");
        c = mDbHelper.fetchColumns(new String[] {"_id","name"});

    }


    // create an array to specify which fields we want to display
    String[] from = new String[]{"name"};
    // create an array of the display item we want to bind our data to
    int[] to = new int[]{android.R.id.text1};
    // create simple cursor adapter
    SimpleCursorAdapter adapter =
        new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, c, from, to );
    mDbHelper.close();

    adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
    // get reference to our spinner
    c.close();
    s.setAdapter(adapter);

}

这是fetchColumns方法,供参考,因为它被用于尝试访问数据库中的数据。
    public Cursor fetchColumns(String[] colnames) {
    Cursor mCursor = database.query(DATABASE_TABLE, colnames, null, 
            null, null, null, null);
    if (mCursor != null) {
        mCursor.moveToFirst();
    }
    return mCursor;
}

Logcat指向了这个方法。上面提到的错误指向getWritableDatabase()方法是罪魁祸首。数据库不为null,我可以使用SQLite数据库浏览器查看其内容。

    public SQLiteDatabase open() throws SQLException {
    dbHelper = new myDbHelper(context);
    database = dbHelper.getWritableDatabase();

    return database;
}

这里是下载数据库的方法。
    public void downloadFile(String file_name) throws IOException {

    URL url = new URL(file_url + file_name);
    URLConnection connection = url.openConnection();
    InputStream response = connection.getInputStream();

    FileOutputStream fos = new FileOutputStream(local_file_path + file_name);
    byte data[] = new byte[1024];
    fos.write(data);
    fos.close();
    response.close();
}

有人对导致问题的原因有什么想法吗?我已经进行了调试和堆栈跟踪,似乎所有的问题都来自于open()方法。以下是堆栈跟踪:

    11-05 19:39:32.861: INFO/Database(9084): sqlite returned: error code = 11, msg = 
            database corruption found by source line 40107
    11-05 19:39:32.861: INFO/Database(9084): sqlite returned: error code = 11, msg =         database disk image is malformed
    11-05 19:39:32.861: ERROR/Database(9084): CREATE TABLE android_metadata failed
    11-05 19:39:32.881: ERROR/Database(9084): Failed to setLocale() when constructing, closing the database
    11-05 19:39:32.881: ERROR/Database(9084): android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed
    11-05 19:39:32.881: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1950)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1818)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
    11-05 19:39:32.881: ERROR/Database(9084):     at com.project.myDbAdapter.open(myDbAdapter.java:42)
    11-05 19:39:32.881: ERROR/Database(9084):     at com.project.Main.fillSpinner(Main.java:77)
    11-05 19:39:32.881: ERROR/Database(9084):     at com.project.Main.onCreate(Main.java:40)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.app.ActivityThread.access$2300(ActivityThread.java:125)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.os.Handler.dispatchMessage(Handler.java:99)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.os.Looper.loop(Looper.java:123)
    11-05 19:39:32.881: ERROR/Database(9084):     at android.app.ActivityThread.main(ActivityThread.java:4627)
    11-05 19:39:32.881: ERROR/Database(9084):     at java.lang.reflect.Method.invokeNative(Native Method)
    11-05 19:39:32.881: ERROR/Database(9084):     at java.lang.reflect.Method.invoke(Method.java:521)
    11-05 19:39:32.881: ERROR/Database(9084):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    11-05 19:39:32.881: ERROR/Database(9084):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    11-05 19:39:32.881: ERROR/Database(9084):     at dalvik.system.NativeStart.main(Native Method)
    11-05 19:39:32.901: ERROR/Database(9084): Deleting and re-creating corrupt database /data/data/com.project/databases/names
    11-05 19:39:32.901: ERROR/Database(9084): android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed
    11-05 19:39:32.901: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1950)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1818)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
    11-05 19:39:32.901: ERROR/Database(9084):     at com.project.myDbAdapter.open(myDbAdapter.java:42)
    11-05 19:39:32.901: ERROR/Database(9084):     at com.project.Main.fillSpinner(SBMain.java:77)
    11-05 19:39:32.901: ERROR/Database(9084):     at com.project.Main.onCreate(SBMain.java:40)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.app.ActivityThread.access$2300(ActivityThread.java:125)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.os.Handler.dispatchMessage(Handler.java:99)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.os.Looper.loop(Looper.java:123)
    11-05 19:39:32.901: ERROR/Database(9084):     at android.app.ActivityThread.main(ActivityThread.java:4627)
    11-05 19:39:32.901: ERROR/Database(9084):     at java.lang.reflect.Method.invokeNative(Native Method)
    11-05 19:39:32.901: ERROR/Database(9084):     at java.lang.reflect.Method.invoke(Method.java:521)
    11-05 19:39:32.901: ERROR/Database(9084):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    11-05 19:39:32.901: ERROR/Database(9084):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    11-05 19:39:32.901: ERROR/Database(9084):     at dalvik.system.NativeStart.main(Native Method)
    11-05 19:39:33.311: INFO/ActivityManager(66): Displayed activity com.project.Main: 552 ms (total 552 ms)

任何帮助都将不胜感激!提前感谢!
以下是可用的代码。
      public void downloadFile(String file_name) throws IOException {

          URL url = new URL(file_url + file_name);
        URLConnection connection = url.openConnection();
        InputStream response = connection.getInputStream();

        FileOutputStream fos = new FileOutputStream(local_file_path + file_name);
         byte data[] = new byte[1024];

         IOUtils.copy(response, fos);
        response.close();
       }

    private void fillSpinner(){
    mDbHelper = new myDbAdapter(this);
    mDbHelper.open();
    Cursor c = mDbHelper.fetchColumns(new String[] {"_id","name"});

    if ( ! c.moveToFirst() ){

    mDbHelper.createRow("Create Name");
    c = mDbHelper.fetchColumns(new String[] {"_id","name"});

    c.close();
    }


    // create an array to specify which fields we want to display
    String[] from = new String[]{"name"};
    // create an array of the display item we want to bind our data to
    int[] to = new int[]{android.R.id.text1};
    // create simple cursor adapter
    SimpleCursorAdapter adapter =
    new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, c, from, to );
    mDbHelper.close();

    adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
    // get reference to our spinner
    c.close();
    s.setAdapter(adapter);

    }

我没有关闭游标。

1个回答

3

没错,你实际上并没有复制文件。

public void downloadFile(String file_name) throws IOException {

    URL url = new URL(file_url + file_name);
    URLConnection connection = url.openConnection();
    InputStream response = connection.getInputStream();

    FileOutputStream fos = new FileOutputStream(local_file_path + file_name);
    byte data[] = new byte[1024];

    //WHERE'S THE BEEF?

    fos.write(data);
    fos.close();
    response.close();
}

此外,手动编写复制代码容易出错。我制作了一个简化版本的Apache Commons:

http://www.touchlab.co/blog/android-mini-commons/

请调用。
IOUtils.copy(response, fos);

好的,我添加了这一行并删除了fos.write(data)。似乎没有任何错误,文件正在复制,我可以拉出它并正常查看条目,但是旋转器没有填充? :( - tricknology
从未亲自使用过带有光标适配器的下拉框,对此我无法提供太多帮助。 - Kevin Galligan
太棒了,问题已解决。感谢您的帮助。我已发布了一个带有可工作代码的编辑。 - tricknology
太好了!我想你是“mini commons”库的第二个用户。只是一个想法。在结尾处调用“fos.close()”,确保输出流被刷新,你不会保持打开文件句柄。 - Kevin Galligan
链接无法使用。 - Awsom3D
即使“like”功能正常,该库几乎肯定已经不可用了。这是10年前的事情了。我相信现在一定存在另一个库来帮助解决这个问题。 - Kevin Galligan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接