2010-03-05 53 views
7

我把我的數據庫字段放在「assets」文件夾中。並使用此代碼blog將數據庫複製到「/ data/data/my_packname/databases /」,(此複製代碼我在運行此應用程序時在onCreate()方法中運行它),然後使用select * from .. 。獲取數據。但它給了我例外:沒有這樣的表。如何使用我自己的sqlite數據庫?

有人告訴我,如果我試圖將文件複製到SQLiteOpenHelper的onCreate(),那就太晚了。因此,複製文件代碼無法複製完整文件。

所以我需要使用adb或ddms先拉數據庫?

那麼,任何人都可以教我如何使用我自己的數據庫? 你能告訴我安裝程序嗎?

回答

1

複製數據庫後,應該在執行任何查詢之前關閉並重新打開SQLiteDatabase對象。我有一個從輸入流中複製數據庫的類似問題,這就是爲我解決的問題。

11

我已經使用了該博客文章中的說明,並發現它們在正確的軌道上通過不必要的擴展SQLiteOpenHelper使問題嚴重複雜化。我有更好的運氣執行以下操作:

  1. 創建通過複製到從資產正確的目錄中創建靜態分貝,但沒有得到自己就這麼掛了繼SQLiteOpenHelper一個工具類格式。

  2. 使用相同的工具類使用SQLiteDatabase.openDatabase()

編輯打開DB:這裏是我創建這個工具類的版本;它不完全,但你會得到漂移。

public class DbUtils { 
    private static final String DB_PATH = "/data/data/com.mypackage.myapp/databases/"; 
    private static final String DB_NAME = "my.db"; 

    public static void createDatabaseIfNotExists(Context context) throws IOException { 
     boolean createDb = false; 

     File dbDir = new File(DB_PATH); 
     File dbFile = new File(DB_PATH + DB_NAME); 
     if (!dbDir.exists()) { 
      dbDir.mkdir(); 
      createDb = true; 
     } 
     else if (!dbFile.exists()) { 
      createDb = true; 
     } 
     else { 
      // Check that we have the latest version of the db 
      boolean doUpgrade = false; 

      // Insert your own logic here on whether to upgrade the db; I personally 
      // just store the db version # in a text file, but you can do whatever 
      // you want. I've tried MD5 hashing the db before, but that takes a while. 

      // If we are doing an upgrade, basically we just delete the db then 
      // flip the switch to create a new one 
      if (doUpgrade) { 
       dbFile.delete(); 
       createDb = true; 
      } 
     } 

     if (createDb) { 
      // Open your local db as the input stream 
      InputStream myInput = context.getAssets().open(DB_NAME); 

      // Open the empty db as the output stream 
      OutputStream myOutput = new FileOutputStream(dbFile); 

      // 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(); 
      myOutput.close(); 
      myInput.close(); 
     } 
    } 

    public static SQLiteDatabase getStaticDb() { 
     return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY); 
    } 
} 
+0

你能分享實用課嗎? 因爲我不明白:「不會讓自己如此掛斷」 非常感謝 – user275788 2010-03-06 12:57:22

+0

我已經添加了我的實用程序類的減少版本,只留下代碼的肉在那裏。 (例如,我強烈建議添加Log語句,但這些示例代碼不是必需的)。無論如何,在這個版本的代碼中,您只需在應用程序啓動時調用createDatabaseIfNotExists(),比如在android.app.Application中擴展onCreate()。 – 2010-03-06 16:30:59

+0

另請注意,如果您的文件大小超過1MB,則read()拋出IoException和資產日誌「數據超出UNCOMPRESSED_DATA_MAX」...我通過在資產中命名我的文件.jpg來解決這個問題 - > aapt沒有試圖壓縮它 – Mikpa 2010-11-14 13:23:00

-1

從您發佈的文章創建數據庫的方式略有不同勢從它如何在Android的例子做了(我不想說,如果它是好還是壞)。

我已經學會了如何使用數據庫從SDKs NotePad sample

這是很好的例子,從開始,becouse它涵蓋通過ContentProvider的兩個數據庫創建主題和數據庫訪問(這是真正從數據庫獲取數據的唯一的好辦法,否則在嘗試從代碼的多個位置同時獲取數據時會遇到問題)。

您應該注意,SQLiteOpenHelper功能非常強大,如果您能夠正確使用它,它將幫助您。例如,它存儲當前的數據庫版本(不是sqlite版本,但是您使用數據庫模式版本進行分配的編號),並且當您使用新的數據庫結構創建新的應用程序版本時,可以將當前模式更新爲onUpdate中的新版本。

+0

我不認爲你理解博客文章的目的; NotePad示例用於創建數據庫,但提問者想要做的是在設備中基於預先存在的sqlite數據庫創建數據庫。 – 2010-03-05 15:35:13

+0

我知道,但提問者也想知道他應該如何在android中使用數據庫,而這些數據庫並未包含在帖子中。 – skyman 2010-03-05 15:44:50

0

這是我的版本從「Silvio Donnini」代碼:), 現在您可以輕鬆地更新數據庫。

private static final String DB_PATH = "/data/data/pakagename/databases/"; 
private static final String DB_NAME = "databaseName";  
private static SQLiteDatabase db; 

public static void createDatabaseIfNotExists(Context context,int version) throws IOException { 
    boolean createDb = false; 

    File dbDir = new File(DB_PATH); 
    File dbFile = new File(DB_PATH + DB_NAME); 
    if (!dbDir.exists()) { 
     dbDir.mkdir(); 
     createDb = true; 
    } 
    else if (!dbFile.exists()) { 
     createDb = true; 
    } 
    else { 
     // Check that we have the latest version of the db  
     db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY); 

     if (db.getVersion() != version) { 
      dbFile.delete(); 
      createDb = true; 
     } 

    } 

    if (createDb) { 

     // Open your local db as the input stream 
     InputStream myInput = context.getResources().openRawResource(R.raw.database); 

     // Open the empty db as the output stream 
     OutputStream myOutput = new FileOutputStream(dbFile); 

     // 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(); 
     myOutput.close(); 
     myInput.close(); 
     SQLiteDatabase dbwrite = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE); 
     dbwrite.setVersion(version); 
     dbwrite.close(); 
     if (db != null) 
      db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY); 

    } 
} 

public static SQLiteDatabase getStaticDb() { 
    if (db != null) 
     return db; 

    return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY); 
} 
0

我知道這是一個古老的問題,但我失去了大量的時間找出它,在所有的答覆的幫助下。


問題是設備將數據庫存儲在他的data/data /.../ databases文件夾中。所以,當你改變某個數據庫(名稱,添加android元數據表,大小..)它不會有任何區別,因爲存儲的數據庫和檢查現有數據庫的方法。


要獲得最新的數據庫,改變它之後,你必須在不檢查現有databses運行的程序(例如,而不是dbExist = checkDataBase();使得它只是假的)。

dbExist = checkDataBase(); 

更改爲:

dbExists = false; 

你拿起 「新」 DATABSE您可以返回到檢查現有的經過。

希望它可以幫助別人, 迪娜

0

我知道這是舊的文章,但對於那些誰仍然獲得了谷歌或Bing搜索後,在這裏,這是解決了上述問題:

在createDataBase()中有

有以下檢查;

this.getReadableDatabase(); 

此檢查是否已經存在與所提供的名稱的數據庫,如果沒有創建一個空數據庫,使得它可以與一個在資產文件夾被覆蓋。在較新的設備上,它可以完美地工作,但有些設備無法正常工作。主要是舊設備。我不知道究竟是什麼原因,但似乎getReadableDatabase()函數不僅獲取數據庫,而且還打開它。如果您然後將資產文件夾中的數據庫複製到它上面,它仍然具有指向空數據庫的指針,並且您將得到表不存在的錯誤。

因此,爲了使所有設備上工作,你應該把它修改爲以下行:

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

即使數據庫在檢查開,此後它被關上,它不會給你任何更多的麻煩。

0

冷靜的傢伙,經過長期的研究終於找到了一個「沒有這樣的表」錯誤

入住Assets文件夾數據庫的名稱,如果是像「DATABASE_NAME.EXTENSION」然後把全名助手類擴展愚蠢的錯誤它解決了我的問題。

就像說資產名稱的數據庫是login.sqlite或login.db什麼的。將DB_NAME = login.sqlite完全擴展。 this tutorial現在完美。

相關問題