【问题标题】:How can I embed an SQLite database into an application?如何将 SQLite 数据库嵌入到应用程序中?
【发布时间】:2011-08-03 09:04:57
【问题描述】:

我认为我有一些基本的理解问题,所以也许有人能够提供帮助:-)

我正在使用 Eclipse 开发一个 Android 应用程序,这个应用程序将使用一个数据库(将只实现从数据库中读取)。该数据库包含大约 4,000 个条目,即不能通过源代码创建和填充数据库。因此,我已经提前创建了包含所有记录的数据库。

但是我怎样才能将这个数据库文件“嵌入”到我的应用程序中然后访问它呢?数据库的文件大小约为 500 kB。从远程服务器下载也不是一种选择,因为这是不允许的。

谢谢, 罗伯特

【问题讨论】:

    标签: android sqlite import


    【解决方案1】:

    ReignDesign 博客上标题为 Using your own SQLite database in Android applications 的好文章。基本上你预先创建了你的数据库,把它放在你的 apk 中的 assets 目录中,并在第一次使用时复制到“/data/data/YOUR_PACKAGE/databases/”目录。

    【讨论】:

      【解决方案2】:

      我通过以下方式解决了这个问题:

      1. file.db 添加到项目/资产文件夹中;

      2. 写下一节课:

        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 可能是有意义的。我想知道在二进制/版本兼容性方面,预先创建数据库会有多少问题。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-11-26
          • 1970-01-01
          • 2021-10-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多