2

我有一个离线创建并放入assets/目录中的预填充数据库。我试图在SQLiteOpenHelper.onCreate()被调用时复制它,但我遇到了严重的麻烦。

public void onCreate(SQLiteDatabase db) {
    importAssets();
}

当我像这样编写代码时,在随后尝试从数据库中获取数据时,我始终会收到no such table错误。我做了一些乱七八糟的事情,开始将 SQL 语句插入到onCreate()调用中importAssets(),例如:

public void onCreate(SQLiteDatabase db) {
    importAssets();
    db.execSQL("CREATE TABLE main_table (some_col);");
}

现在,当我运行应用程序时,我遇到了列未找到错误的问题(上述架构与数据库访问代码所期望的不匹配,它缺少许多列。在应用程序的第二次运行时,android_metatdata被损坏,然后一切都下地狱了。在调用之前我也尝试过使用 SQL 代码,但importAssets()结果同样是灾难性的。

所以我开始认为我正在做的文件副本importAssets()基本上被截断了onCreate()。我对吗?onCreate()是直接使用 SQL创建数据库的唯一方法吗?我可以不使用这个功能来复制现成的数据库assets/吗?

importAssets()我已经通过Log()调用确认它运行正常。这是完整的功能:

private void importAssets() throws IOException
{  
    AssetManager am = mCtx.getAssets();
    InputStream in = am.open(DB_NAME);
    FileOutputStream out;
    byte[] buffer = new byte[1024];
    int len;
    File db;

    db = new File(DB_DIR + "/" + DB_NAME);

    // copy the DB from assets to standard DB dir created above
    out = new FileOutputStream(db);
    while ((len = in.read(buffer)) > 0)
    {
        out.write(buffer, 0, len);
    }

    out.flush();
    out.close();
    in.close();
    if (!db.exists())
    {
        Log.e(TAG, DB_DIR + "/" + DB_NAME + " does not exist");
    }
}

我在其他地方看到了我在 SQLiteOpenHelper 构造函数中进行文件复制的建议,但这意味着我必须手动检查文件是否存在,importAssets()因为每次使用数据库时都会调用构造函数。此外,onCreate()这对于我想做的事情实际上是无用的,尽管我没有看到任何避免这种情况的方法。

4

1 回答 1

2

我现在确信我的怀疑是对的。的onCreate()函数SQLiteOpenHelper将创建数据库文件,在name调用超类构造函数的参数中指定。onCreate()然后,它希望您使用各种 DB 库从函数内修改此 DB 文件(添加表、数据、更改表等) 。从其他地方复制文件只会被截断

我不知道它是如何或为什么这样做的,但这onCreate()对于通过完整地复制数据库来“创建”数据库毫无用处,assets/这正是我所需要的。我已经移动importAssets()到构造函数并添加了适当的检查,如果它已经存在,则不会覆盖它。什么onCreate()都没有,它似乎并没有扰乱其他地方正在发生的事情。

我认为这SQLiteOpenHelper确实需要运行 SQLite 脚本的能力。这样我就不必将长长的 SQL 块硬编码到我的 Java 代码中,而我真正想要做的只是获得一个数据库设置。

于 2012-11-17T22:08:02.133 回答