我将数据库字段放在“assets”文件夹中。并使用此blog中的代码将数据库复制到“/ data / data / my_packname / databases /”,(此复制代码我在运行此应用程序时在onCreate()方法中运行它)然后使用select * from ...来获取数据。但它给了我一个例外:没有这样的表。
有人告诉我,如果我试图在SQLiteOpenHelper的onCreate()中复制文件,那就太晚了。因此复制文件代码无法复制整个文件。
所以我需要先用adb或ddms拉数据库吗?
那么,任何人都可以教我如何使用自己的数据库? 你能告诉我这个设置吗?
答案 0 :(得分:12)
我已经使用了该博文中的说明,发现它们在正确的轨道上通过不必要地扩展SQLiteOpenHelper
来严重地使问题复杂化。我做了以下更好的运气:
创建一个实用程序类,通过将静态数据库从资产复制到正确的目录中来创建静态数据库,但不会因为SQLiteOpenHelper格式而陷入困境。
使用相同的实用程序类,使用SQLiteDatabase.openDatabase()
编辑:这是我创建的这个实用程序类的一个版本;它不是很完整,但你会得到漂移。
public class DbUtils {
private static final String DB_PATH = "/data/data/com.mypackage.myapp/databases/";
private static final String DB_NAME = "my.db";
public static void createDatabaseIfNotExists(Context context) throws IOException {
boolean createDb = false;
File dbDir = new File(DB_PATH);
File dbFile = new File(DB_PATH + DB_NAME);
if (!dbDir.exists()) {
dbDir.mkdir();
createDb = true;
}
else if (!dbFile.exists()) {
createDb = true;
}
else {
// Check that we have the latest version of the db
boolean doUpgrade = false;
// Insert your own logic here on whether to upgrade the db; I personally
// just store the db version # in a text file, but you can do whatever
// you want. I've tried MD5 hashing the db before, but that takes a while.
// If we are doing an upgrade, basically we just delete the db then
// flip the switch to create a new one
if (doUpgrade) {
dbFile.delete();
createDb = true;
}
}
if (createDb) {
// Open your local db as the input stream
InputStream myInput = context.getAssets().open(DB_NAME);
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(dbFile);
// 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();
}
}
public static SQLiteDatabase getStaticDb() {
return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}
}
答案 1 :(得分:1)
复制数据库后,应尝试关闭并重新打开SQLiteDatabase对象,然后再对其执行任何查询。从输入流中复制数据库时遇到了类似的问题,这就是解决它的问题。
答案 2 :(得分:0)
这是我的版本来自“Silvio Donnini”代码:), 现在您可以轻松更新数据库了。
private static final String DB_PATH = "/data/data/pakagename/databases/";
private static final String DB_NAME = "databaseName";
private static SQLiteDatabase db;
public static void createDatabaseIfNotExists(Context context,int version) throws IOException {
boolean createDb = false;
File dbDir = new File(DB_PATH);
File dbFile = new File(DB_PATH + DB_NAME);
if (!dbDir.exists()) {
dbDir.mkdir();
createDb = true;
}
else if (!dbFile.exists()) {
createDb = true;
}
else {
// Check that we have the latest version of the db
db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
if (db.getVersion() != version) {
dbFile.delete();
createDb = true;
}
}
if (createDb) {
// Open your local db as the input stream
InputStream myInput = context.getResources().openRawResource(R.raw.database);
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(dbFile);
// 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();
SQLiteDatabase dbwrite = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE);
dbwrite.setVersion(version);
dbwrite.close();
if (db != null)
db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}
}
public static SQLiteDatabase getStaticDb() {
if (db != null)
return db;
return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}
答案 3 :(得分:0)
我知道这是一个老问题,但在所有回复的帮助下,我失去了很多时间来搞清楚。
问题是设备将数据库存储在其data / data /.../ databases文件夹中。所以,当你改变数据库(名称,添加android元数据表,大小......)时,由于存储的数据库和检查现有数据库的方法,它不会有任何区别。
要获取最新的数据库,在更改它之后,必须运行该程序而不检查现有的数据库(例如,而不是dbExist = checkDataBase();
使其只是假)。
dbExist = checkDataBase();
更改为:
dbExists = false;
拿起“新”数据库后,您可以返回检查现有数据库。
希望它对某人有帮助, 迪娜
答案 4 :(得分:0)
我知道这是一篇旧帖子,但是对于那些在Google或Bing搜索后仍然在这里的人来说,这是所述问题的解决方案:
在createDataBase()中有以下检查;
this.getReadableDatabase();
这将检查是否已存在具有所提供名称的数据库,如果没有,则创建一个空数据库,以便可以使用assets文件夹中的数据库覆盖该数据库。在较新的设备上,这可以完美地工作,但有一些设备无法正常工作。主要是旧设备。我不确切知道为什么,但似乎getReadableDatabase()函数不仅获取数据库而且还打开它。如果您随后从assets文件夹复制数据库,它仍然具有指向空数据库的指针,您将获得表不存在错误。
因此,为了使其适用于所有设备,您应该将其修改为以下几行:
SQLiteDatabase db = this.getReadableDatabase();
if (db.isOpen()){
db.close();
}
即使数据库在支票中被打开,它也会在此后关闭,它不会给您带来任何麻烦。
答案 5 :(得分:0)
冷静下来,经过长时间的研究终于找到了“没有这样的表”错误的愚蠢错误
检查Assets文件夹中的数据库名称,如果它类似于“DATABASE_NAME.EXTENSION”,然后在Helper类中使用扩展名来解决我的问题。
就像资产数据库中的名称是login.sqlite或login.db一样。将DB_NAME = login.sqlite完全放在extention中。 this tutorial现在效果很好。答案 6 :(得分:-1)
从您发布的文章创建数据库的方式与在android示例中完成的方式略有不同(我不想说它是好还是坏)。
我已经学会了如何使用SDKs NotePad sample
中的数据库这是一个很好的例子,因为它涵盖了数据库创建主题和通过ContentProvider进行数据库访问(它实际上是从db获取数据的唯一好方法,否则当尝试从许多地方同时获取数据时你会遇到问题你的代码)。
你应该注意到SQLiteOpenHelper非常强大,如果你能正确使用它,“它会帮助你”。例如,它存储当前数据库版本(不是sqlite版本,但是您使用数据库模式版本编号),当您使用新数据库结构创建新应用程序版本时,可以将当前模式更新为onUpdate中的新版本。