7

伙计们,我在将数据库从本地资产文件夹复制到 /data/data/package_name/databases 目录时遇到问题。当我使用http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/ 教程来做这件事时,我只能得到一个空文件。

我引用了 copyDataBase() 方法的一部分,没有区别。每次应用程序启动时,它都会创建目录和空数据库。那么有什么方法可以使 copyDataBase() 工作?

非常感谢你!!

4

5 回答 5

15

为什么不从资产中复制?这样做是完全正常的。但是您不能在 onCreate 中执行此操作,此时已经创建了一个空数据库。你需要事先做。我通常在覆盖 getWriteableDatabase 时这样做,比如

public synchronized SQLiteDatabase getWritableDatabase() {
    SQLiteDatabase db = null;

    if (!doesDatabaseExist()) {
        try {
            copyDatabase();
            db = super.getWritableDatabase();
        } catch(Exception ex) {
            Log.e("Database Log", getDatabasePath() + " failed to copy correctly. " + ex.getLocalizedMessage());
        }
    }
    else {
        db = super.getWritableDatabase();
    }

    return db;
}
于 2011-06-30T20:59:00.400 回答
1

我不会从-文件夹中复制任何数据库assets如果您在数据库中需要一些标准条目,您可以在您的-method中使用INSERTs添加它们。onCreate()


更新:由于这是错误的投票(这有点正确)并且我无法删除它,所以这里有一些更新。

我想说这取决于您要添加到数据库中的标准条目的数量。如果只是一两个,那么运送一个打包好的数据库可能不值得。

无论如何,一些应用程序带有相当大的数据库(例如,食谱集合)。您显然不能在代码中添加所有这些。

  • 对于小型测试条目,我仍然更喜欢简单地将它们添加到onCreate().
  • 对于更大的数据库,您应该预先填充它们并将它们与您的应用程序一起发布。

为了使后者工作,您需要将数据库文件从复制assets/到您的应用程序文件夹。有一个不错的库可以为您处理:android-sqlite-asset-helper

于 2011-05-25T06:43:32.203 回答
1

我不知道它是否仍然有用,但这是其他人到这里看遮阳篷的解决方案。您使用的代码适用于大多数手机,一些旧手机与 getReadableDatabase() 函数有不同的行为。因此,您的问题不在 copyDataBase 函数中,而是在 createDataBase 函数中。

在 createDataBase() 中有以下检查;

this.getReadableDatabase();

这将检查是否已经存在具有所提供名称的数据库,如果没有,则创建一个空数据库,以便可以用 assets 文件夹中的数据库覆盖它。在较新的设备上,这可以完美地工作,但在某些设备上这不起作用。主要是旧设备。我不知道确切原因,但似乎 getReadableDatabase() 函数不仅获取数据库而且还打开它。如果您然后从资产文件夹中复制数据库,它仍然具有指向空数据库的指针,您将得到表不存在错误。

因此,为了使其适用于所有设备,您应该将其修改为以下几行:

SQLiteDatabase db = this.getReadableDatabase();
if (db.isOpen()){
    db.close();
}

即使在检查中打开了数据库,之后又关闭了,也不会给你带来任何麻烦。

于 2013-07-20T23:44:43.893 回答
0

在上面的例子中,我以这种方式工作:

db = super.getWritableDatabase();
db.close;
copyDatabase();

否则我得到一个 IO 错误;

于 2012-07-21T17:40:25.677 回答
0

这是我使用的简单方便的代码:

public class DataBaseImportHelper {
    private DataBaseImportHelper() {}; // Avoid instantiation

/**
 * Creates a empty database on the system and rewrites it with your own database.
 */
public static boolean importDataBase(Context context) {
    InputStream myInput = null;
    OutputStream myOutput = null;
    try {
        // Open local db from assets as the input stream
        myInput = context.getAssets().open(DATABASE_NAME);
        createEmptyDatabase(context); // See this method below
        // Open the empty db as the output stream
        myOutput = new FileOutputStream(getDatabaseFile(context));

        // 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();
        myInput.close();
        myOutput.close();
        return true;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return false;
}

/**
 * Check if the database already exists.
 * @return true if it exists, false if it doesn't
 */
public static boolean isDatabaseExists(Context context) {
    return getDatabaseFile(context).exists();
}

private static File getDatabaseFile(Context context) {
    return context.getDatabasePath(DatabaseHelper.DATABASE_NAME);
}

/**
 * Create an empty database into the default application database
 * folder.So we are gonna be able to overwrite that database with our database
 */
private static void createEmptyDatabase(Context context) {
            // use anonimous helper to create empty database
    new SQLiteOpenHelper(context, DatabaseHelper.DATABASE_NAME, null, 1) {
                    // Methods are empty. We don`t need to override them
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
        }
    }.getReadableDatabase().close();
}

}

并在代码中使用:

if(!DataBaseImportHelper.isDatabaseExists(this)){
    if (!DataBaseImportHelper.importDataBase(this)){
            throw new IllegalStateException("Database doesn`t exist and hasn`t been copied!");
    }
}
于 2013-02-20T07:20:10.273 回答