如何将 SQLite 数据库嵌入到应用程序中?
Posted
技术标签:
【中文标题】如何将 SQLite 数据库嵌入到应用程序中?【英文标题】:How can I embed an SQLite database into an application? 【发布时间】:2011-08-03 09:04:57 【问题描述】:我认为我有一些基本的理解问题,所以也许有人能够提供帮助:-)
我正在使用 Eclipse 开发一个 android 应用程序,这个应用程序将使用一个数据库(将只实现从数据库中读取)。该数据库包含大约 4,000 个条目,即不能通过源代码创建和填充数据库。因此,我已经提前创建了包含所有记录的数据库。
但是我怎样才能将这个数据库文件“嵌入”到我的应用程序中然后访问它呢?数据库的文件大小约为 500 kB。从远程服务器下载也不是一种选择,因为这是不允许的。
谢谢, 罗伯特
【问题讨论】:
【参考方案1】:ReignDesign 博客上标题为 Using your own SQLite database in Android applications 的好文章。基本上你预先创建了你的数据库,把它放在你的 apk 中的 assets 目录中,并在第一次使用时复制到“/data/data/YOUR_PACKAGE/databases/”目录。
【讨论】:
【参考方案2】:我通过以下方式解决了这个问题:
将file.db
添加到项目/资产文件夹中;
写下一节课:
public class LinnaeusDatabase extends SQLiteOpenHelper
private static String DATABASE_NAME = "Dragonfly.db";
public final static String DATABASE_PATH = "/data/data/com.kan.linnaeus/databases/";
private static final int DATABASE_VERSION = 1;
private SQLiteDatabase dataBase;
private final Context dbContext;
public LinnaeusDatabase(Context context)
super(context, DBActivity.DatabaseName, null, DATABASE_VERSION);
this.dbContext = context;
DATABASE_NAME = DBActivity.DatabaseName;
// checking database and open it if exists
if (checkDataBase())
openDataBase();
else
try
this.getReadableDatabase();
copyDataBase();
this.close();
openDataBase();
catch (IOException e)
throw new Error("Error copying database");
Toast.makeText(context, "Initial database is created", Toast.LENGTH_LONG).show();
private void copyDataBase() throws IOException
InputStream myInput = dbContext.getAssets().open(DATABASE_NAME);
String outFileName = DATABASE_PATH + DATABASE_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0)
myOutput.write(buffer, 0, length);
myOutput.flush();
myOutput.close();
myInput.close();
public void openDataBase() throws SQLException
String dbPath = DATABASE_PATH + DATABASE_NAME;
dataBase = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READWRITE);
private boolean checkDataBase()
SQLiteDatabase checkDB = null;
boolean exist = false;
try
String dbPath = DATABASE_PATH + DATABASE_NAME;
checkDB = SQLiteDatabase.openDatabase(dbPath, null,
SQLiteDatabase.OPEN_READONLY);
catch (SQLiteException e)
Log.v("db log", "database does't exist");
if (checkDB != null)
exist = true;
checkDB.close();
return exist;
【讨论】:
【参考方案3】:在对this answer 的评论中,CommonsWare 建议不要使用@evilone 在此处提出的相同方法(即,自己从资产中复制数据库)。相反,您应该使用久经考验的SQLiteAssetHelper
。我在 Android Studio 中使用过,效果很好。
directions 相当清晰。以下是一些关键摘录:
如果您使用的是 Gradle 构建系统,只需添加以下内容
build.gradle
文件中的依赖项:
dependencies
compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
像平常一样扩展
SQLiteAssetHelper
SQLiteOpenHelper
, 为构造函数提供数据库名称和版本号:
public class MyDatabase extends SQLiteAssetHelper
private static final String DATABASE_NAME = "northwind.db";
private static final int DATABASE_VERSION = 1;
public MyDatabase(Context context)
super(context, DATABASE_NAME, null, DATABASE_VERSION);
将您的数据库放入assets/databases/northwind.db
(使用您拥有的任何数据库名称)。
第一次使用数据库
getReadableDatabase()
或getWritableDatabase()
被调用。
【讨论】:
【参考方案4】:我过去通过将 JSON 文件存储在 res/raw
资源中的应用程序中,然后在首次加载时加载文件来完成此操作。从那里,您可以使用批量插入模式批量导入条目。请参阅 my database loader for Units 作为此技术的示例。 res/raw
样式的一个好处是您可以使用 Android 资源选择系统将数据本地化到不同的区域,因此您可以针对不同的语言或区域拥有不同的数据库(或其中的一部分)。
您还可以将原始 SQL 转储放在类似的文件中,并在首次加载时加载该文件。您可以使用openRawResource(int) 从资源中获取文件。我建议这样做,而不是存储预制的 sqlite 数据库文件,以增加 sqlite 版本之间的兼容性,并使数据库维护更容易(从应用程序开发生命周期 POV)。
批量加载时,请确保使用事务,因为这将有助于加快加载速度并使加载更加可靠。
【讨论】:
史蒂夫,我喜欢这个主意。您是否有在线代码示例、博客文章或教程? 我已经更新了我的答案,其中包含一些使用这种技术的代码的链接。 据我所知,JSON 文件将存储在一个字符串变量中,然后传递给 Android 中的 JSON 解析,对吗?这个 JSON 文件/字符串可以有多大?在我的应用程序中,它大约为 250-500 kB。 是的,这可能有问题。在您的情况下,如果您想以不只是 sqlite 数据库的格式存储它,那么将其存储为 SQL 可能是有意义的。我想知道在二进制/版本兼容性方面,预先创建数据库会有多少问题。以上是关于如何将 SQLite 数据库嵌入到应用程序中?的主要内容,如果未能解决你的问题,请参考以下文章