TShopping

 找回密碼
 註冊
搜索
查看: 145|回復: 0

[教學] 從 assets 資料夾讀取一個已經存在的資料庫

[複製鏈接]
發表於 2018-8-29 21:33:21 | 顯示全部樓層 |閱讀模式
 
Push to Facebook Push to Plurk Push to Twitter 
資料庫存取相關的 Android 類別,包含了 SQLiteOpenHelper, SQLiteDatabase, Cursor 等,介紹如何從 assets 資料夾讀取一個已經存在的資料庫,並將之寫入 /data/data/<package name>/databases 裡,若使用 ADT Bundle (Eclipse),assets 資料夾位於 Project 的根目錄下,若使用 Android Studio,您必須在 /app/src/main 自行建立 assets 資料夾 [1]。

有一些應用程式會需要讀取已經建立好的資料庫,例如一個試題測驗應用程式,裡面的試題可能已經於電腦上,使用任何的 SQLite 資料庫產生工具,產生一個資料庫檔案(例如:questions.db),我們會希望我們的應用程式能夠直接讀取這個檔案,而不是在應用程式第一次執行時,利用程式去做 INSERT 的動作,下面將示範如何實作出這樣的功能。

第一個步驟是產生 SQLite 資料庫檔案,產生資料庫檔案的工具很多,其中一個是到 SQLite 的官方網站[1]下載,以 Windows 作業系統為例,網站有提供一個已經編譯好的命令列工具 sqlite3.exe,首先進入 Windows 所提供的『命令提示字元』,進入放置 sqlite3.exe 的資料夾後就可以執行它,執行時後面加個檔案名稱當參數,下面是一個範例:

C:\>sqlite3 questions.db

SQLite version 3.7.8 2011-09-19 14:49:19

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite> create table questions(_question, _type, _answer);

sqlite> insert into questions values("1+1", "Math", "2");

sqlite> .exit

在上面的範例中,我們做了兩件事,首先建立一個表格,接著再插入一筆資料到表格內,我們可以再次執行 sqlite3,來驗證資料是否有正確被寫入:

C:\>sqlite3 questions.db

SQLite version 3.7.8 2011-09-19 14:49:19

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite> select * from questions;

1+1|Math|2

除然而為了讓資料庫能夠正常地被 Android 所讀取,有兩點必須注意:

表格必須有一個名為『_id』的欄位,且 type 要設成『INTEGER PRIMARY KEY』。

必須建立一個名為『android_metadata』的表格,表格中要建立一個名為『locale』的欄位,經筆者的測試,我們不需要新增任何記錄。

產生好 questions.db 後我們就可以把這個檔案放到 assets 資料夾,接著就是要進行程式的撰寫:

  1. package lincyu.demo.database_from_outside;

  2. import java.io.FileOutputStream;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;

  5. import android.content.Context;
  6. import android.database.sqlite.SQLiteDatabase;
  7. import android.database.sqlite.SQLiteException;
  8. import android.database.sqlite.SQLiteOpenHelper;

  9. class DatabaseHelper extends SQLiteOpenHelper {

  10.     private static String DB_PATH = "/data/data/" +
  11.         "lincyu.demo.database_from_outside" + "/databases/";
  12.     private static String DB_NAME = "questions.db";

  13.     private final Context mCtx;

  14.     public DatabaseHelper(Context context) {
  15.         super(context, DB_NAME, null, 1); 24 this.mCtx = context;
  16.     }
  17.    
  18.     public boolean createDatabase() {
  19.         boolean dbExist = checkDatabase();
  20.         this.getReadableDatabase();
  21.         if (dbExist == false) {
  22.             if (copyDatabase() == false) {
  23.                 return false;
  24.             }
  25.         }
  26.         return true;
  27.     }

  28.     private boolean checkDatabase() {
  29.         SQLiteDatabase checkDB = null;
  30.         String dbpath = DB_PATH + DB_NAME;
  31.         try {
  32.             checkDB = SQLiteDatabase.openDatabase(dbpath,
  33.                 null, SQLiteDatabase.OPEN_READONLY);
  34.         } catch (SQLiteException e) {
  35.             return false;
  36.         }
  37.         if (checkDB != null) {
  38.             checkDB.close();
  39.             return true;
  40.         }
  41.         return false;
  42.     }

  43.     private boolean copyDatabase() {
  44.         try {
  45.             InputStream input = mCtx.getAssets().open(DB_NAME);
  46.             this.getReadableDatabase();
  47.             String outFileName = DB_PATH + DB_NAME;
  48.             OutputStream output =
  49.             new FileOutputStream(outFileName);
  50.             byte [] buffer = new byte[1024];
  51.             int length;
  52.             while ((length = input.read(buffer)) > 0) {
  53.                 output.write(buffer, 0, length);
  54.             }
  55.             output.flush();
  56.             output.close();
  57.             input.close();
  58.         } catch (Exception e) {
  59.             return false;
  60.         }
  61.         return true;
  62.     }

  63.     @Override
  64.     public void onCreate(SQLiteDatabase db) {
  65.     }

  66.     @Override
  67.     public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
  68.     }
  69. }
複製代碼

從程式碼我們不能發現,其實就只是單純的讀寫檔案,然而必須一提的是,要存取 assets 資料夾必須利用 Context 類別的 getAssets 方法來存取,getAssets 會回傳一個 AssetManager 物件,再呼叫其 open,就可讀取 assets 資料夾下的檔案。

參考資料

[1] Where to place Assets folder in Android Studio - Stack Overflow, http://stackoverflow.com/questions/18302603/where-to-place-assets-folder-in-android-studio

https://ithelp.ithome.com.tw/articles/10158728

 

臉書網友討論
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2018-11-15 20:18 , Processed in 0.053438 second(s), 21 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表