【问题标题】:Cannot Copy DB from assets/ in SQLiteOpenHelper无法从 SQLiteOpenHelper 中的 assets/ 复制数据库
【发布时间】:2012-11-16 07:33:28
【问题描述】:

我有一个预填充的数据库,我已离线创建并放入 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);");
}

现在,当我运行应用程序时,我遇到了 column not found 错误(上面的架构与 DB 访问代码所期望的不匹配,它缺少一些列。在应用程序的第二次运行,android_metatdata 被破坏,然后一切都陷入困境。我还尝试使用importAssets() 调用之前的 SQL 代码,结果同样是灾难性的。

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

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

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");
    }
}

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

【问题讨论】:

    标签: android android-sqlite android-assets


    【解决方案1】:

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

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

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

    【讨论】:

    • 谢谢。您的回答使我找到了解决方案。我基本上做了 3 件事,并且全部在构造函数中完成,并且只有当 dbFile 不存在时(其中dbFile = context.getDatabasePath(DB_NAME)),第一个是调用dbFile.getParentFile().mkdirs() 然后dbFile.createNewFile(),最后从资产中复制数据库.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多