首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Android 預置資料庫:將 SQLite 檔放入 assets 目錄並在首次啟動複製到可寫入路徑

     編輯:程式設計疑難解答

適用場景

  • App 內建大量唯讀資料(字典、郵遞區號、產品目錄)。
  • 資料不需使用者編輯,或僅需少量增量同步。

實作步驟

1. 準備資料庫檔案

  • 用 DB Browser for SQLite / Navicat 建立 mydict.db,建立資料表並匯入資料。
  • 確認表結構、索引正確。

2. 放入專案

app/src/main/assets/mydict.db  (或 assets/databases/mydict.db)

3. 資料庫輔助類:首次啟動複製 assets → 內部儲存

public class DbOpenHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "mydict.db";
    private static final int DB_VERSION = 1;
    private final Context context;
    private SQLiteDatabase database;
    private final String dbPath;

    public DbOpenHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        this.context = context;
        this.dbPath = context.getDatabasePath(DB_NAME).getAbsolutePath();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // 不建表,改用複製法
        copyDatabaseFromAssets();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // 版本升級策略:刪除舊檔再複製新檔(簡單但會清除用戶資料)
        context.deleteDatabase(DB_NAME);
        copyDatabaseFromAssets();
    }

    private void copyDatabaseFromAssets() {
        try (InputStream is = context.getAssets().open(DB_NAME);
             OutputStream os = new FileOutputStream(dbPath)) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
            os.flush();
        } catch (IOException e) {
            throw new RuntimeException("複製預置資料庫失敗", e);
        }
    }

    public SQLiteDatabase openDatabase() {
        if (database == null || !database.isOpen()) {
            database = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READWRITE);
        }
        return database;
    }

    @Override
    public synchronized void close() {
        if (database != null) database.close();
        super.close();
    }
}

4. 使用範例

DbOpenHelper helper = new DbOpenHelper(this);
SQLiteDatabase db = helper.openDatabase();
Cursor c = db.rawQuery("SELECT word, detail FROM dict WHERE word LIKE ?", new String[]{"%apple%"});
while (c.moveToNext()) {
    String word = c.getString(0);
    String detail = c.getString(1);
    // 顯示...
}
c.close();

注意事項

  • 資料庫版本升級:若採「刪除重複製」,用戶本地收藏/筆記會消失。生產環境建議改用 **SQL 差分腳本** 或 **Room Migration**。
  • 唯讀開啟:若資料純唯讀,可用 SQLiteDatabase.OPEN_READONLY 避免寫入鎖。
  • 大檔案分割:assets 單檔超過 1MB 可能打包問題,可分割為 mydict.db.001, .002 啟動時合併,或改用 Room 預打包資料庫(createFromAsset)。
  • Room 整合:Room.databaseBuilder(context, AppDatabase::class.java, DB_NAME).createFromAsset("mydict.db").build() 一行搞定複製與遷移。

總結

將 SQLite 檔放入 assets/,SQLiteOpenHelper.onCreate 中複製至 context.getDatabasePath(),即可實現 App 內建資料庫。新專案強烈建議直接使用 **Room + createFromAsset** 簡化流程。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved