我有一个预先填充的数据库,我已经离线创建并放入assets/
目录。我试图在调用SQLiteOpenHelper.onCreate()
时复制它,但我遇到了严重问题。
public void onCreate(SQLiteDatabase db) {
importAssets();
}
当我编写这样的代码时,在随后尝试从数据库中获取数据时,我始终会遇到没有这样的表错误。我做了一些事情,开始在onCreate()
中插入SQL语句以及调用importAssets()
,例如:
public void onCreate(SQLiteDatabase db) {
importAssets();
db.execSQL("CREATE TABLE main_table (some_col);");
}
现在,当我运行应用程序时,我遇到了列未找到错误的问题(上述架构与数据库访问代码所需的内容不匹配,它缺少许多列。应用程序的第二次运行,android_metatdata
被破坏,然后一切都变成了地狱。我也在importAssets()
调用之前尝试了SQL代码,结果也是类似的灾难。
所以我开始认为我在importAssets()
中所做的文件副本基本上被onCreate()
截断了。我对吗?是通过直接使用SQL在onCreate()
中创建数据库的唯一方法吗?我是否可以不使用此功能从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");
}
}
我已经看到elsewhere建议我在SQLiteOpenHelper构造函数中执行文件复制,但这意味着我必须手动检查importAssets()
中文件是否存在,因为构造函数得到了每次我使用DB时调用。此外,onCreate()
对我想做的事情实际上没用,但我认为没有办法避免这种情况。
答案 0 :(得分:2)
我现在确信我的怀疑是正确的。 onCreate()
的{{1}}函数将创建DB文件,该文件在对超类构造函数的调用的SQLiteOpenHelper
参数中指定。然后,它希望您使用各种DB库从name
函数中修改此DB文件(添加表,数据,更改表等)。 从其他地方复制文件只会被截断。
我不知道它是如何或为什么这样做的,但这使onCreate()
无法通过从onCreate()
完整地复制它来“创建”数据库,这正是我所需要的。我已将assets/
移动到构造函数并添加了相应的检查,以便在它已经存在的情况下不会覆盖它。 importAssets()
根本没有任何内容,似乎并没有破坏其他地方发生的事情。
我认为onCreate()
确实需要运行SQLite脚本的能力。这样我就不必将长长的SQL代码硬编码到我的Java代码中,而我真正想做的就是进行数据库设置。