Android:从资产文件夹复制数据库,但只获取一个空文件

时间:2011-05-25 06:31:24

标签: android sqlite android-assets

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

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

非常感谢!!

5 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:1)

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

在createDataBase()中有以下检查;

this.getReadableDatabase();

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

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

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

即使数据库在支票中被打开,它也会在此后关闭,它不会给您带来任何麻烦。

答案 2 :(得分:0)

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


更新:由于这是因为错误而被投票(这有点正确)而且我无法删除它,这里有一点点更新。

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

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

  • 对于小型测试条目,我仍然希望只在assets/中添加它们。
  • 对于较大的数据库,您应该预先填充它们并将其与您的应用一起发送。

要使后者工作,您需要将数据库文件从{{1}}复制到您的app-folder。有一个很好的库可以为您处理:android-sqlite-asset-helper

答案 3 :(得分:0)

上面右边的例子就是这样对我工作的:

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

否则我收到IO错误;

答案 4 :(得分: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!");
    }
}