2010-05-22 145 views
28

是否有可能將res/raw資源目錄中存儲的csv文件用於填充sqlite3數據庫中的表?從CSV文件填充Android數據庫?

我的想法是,如果有一種方法可以將整個文件批量導入到表中,那麼這將比遍歷文件中的每一行並執行單個插入語句更清晰和更快速...

我發現有一個SQLite導入命令,允許這樣的:How to import load a .sql or .csv file into SQLite?

...但我有申請在我的Android應用程序的語句的麻煩。我的第一個想法是嘗試類似以下的東西...但沒有運氣:

db.execSQL("CREATE TABLE " + TABLE_NAME + "(id INTEGER PRIMARY KEY, name TEXT)"); 
db.execSQL(".mode csv"); 
db.execSQL(".import res/raw/MyFile.csv " + TABLE_NAME); 

這可能嗎?

我應該嘗試一種不同的方法來填充我的數據庫嗎?

更新:我標記約瑟夫的答案作爲答案(批量插入使用交易),因爲它工作正常,並根據我的標題直接回答我的問題(謝謝約瑟夫)。但是,我仍然在尋找一種方法,使用import語句將csv文件中的Android應用程序批量插入到sqlite3表中。如果你知道如何做到這一點,請回復。

謝謝你的答案!

回答

30

如果您想要將靜態數據打包到您的應用程序中,我建議您在開發時準備數據庫(使用您喜歡的任何UI或csv-import命令)並將sqlite文件發送到assets文件夾中。當你的應用程序第一次運行時,你可以簡單地將整個sqlite文件複製到設備上。 Theseposts帶你通過這個想法,這很可能是建立數據庫的最快方式(文件複製速度)。

如果由於某種原因,您確實需要在運行時插入大量數據,那麼我建議您查看bulk insert using transactions的加速方法。

+0

感謝您的答覆Josef,我試圖在.apk的資產文件夾中發佈sqlite3 .db文件(就像reigndesign發佈的輪廓)。我在使用reigndesign解決方案時遇到的問題是,當我的數據庫版本#更改時,onUpgrade()不會被調用。實際上,我可以用新版本取代現有數據庫的唯一方法是解決onUpgrade()並添加一個語句,它在調用createDataBase()之前顯式刪除數據庫(這基本上會迫使你每次運行Activity時重新創建數據庫... =( – MoMo 2010-05-22 18:04:11

+0

至於使用可能是可行的解決方案的事務,我在實現此解決方案時能夠獲得onUpgrad()的調用一致性(http:// www .screaming-penguin.com/node/7742),但考慮到獲得reigndesign解決方案工作所需的升級和調整(即'_id'列和'android_metadata'表),一個簡單的sql導入語句仍然是理想的。調整並不難實現我擔心它會增加不必要的依賴關係,以便Android平臺期望他們的數據庫被創建。如果這樣做會改變,那麼我們的解決方案... – MoMo 2010-05-22 18:15:23

+3

使用預建sqlite3 fil e不是很好的做法。製造商可以實施/利用他們想要的任何技術,但必須堅持sqlite3接口 - 所以你的預編譯sqlite3可能無法在某些設備上工作。因此,最好/最安全的做法是始終讓設備創建數據庫,然後批量導入。 – straya 2012-03-02 04:07:44

14

我花了很多時間尋找一個簡單的解決方案,並自己提出了一點代碼。對於未來的人找這個,好像我是你可以使用這個:

BufferedReader in = new BufferedReader(your csv file source here); 
String reader = ""; 
while ((reader = in.readLine()) != null){ 
    String[] RowData = reader.split(","); 
    date = RowData[0]; 
    value = RowData[1]; 
    ContentValues values = new ContentValues(); 
    values.put(CsvProvider.DATE, date); 
    values.put(CsvProvider.VALUE, value); 
    getContentResolver().insert(CsvProvider.CONTENT_URI, values); 
} 
in.close(); 

CSV文件沒有標題,只有2列,但兩個以上的列不應該是一個問題。只記得指定什麼是拆分你的列,併爲每個列添加另一個RowData[#](你必須以0開頭)。您要確保在打電話給in.close()之前,每條線都要完成。我使用的是內容提供商,但您可以根據自己的喜好將數據附加到String[]或其他任何地方。

當我使用輸入流時,您可以將BufferedReader指向任何你想要的位置。只要BufferedReader可以讀取它,那麼它將工作。

+0

它不適用於「|」分隔器... ? – kthorat 2010-11-22 20:29:32

+1

分隔符是一種痛苦。我不知道爲什麼人們用它來開始。我試圖從文件中刪除它,它只是停留。有什麼方法可以使用逗號或其他字符,還是來自某個Web服務器的地方? – Opy 2010-11-22 21:54:25

+0

沒有..它必須是「|」,因爲有700-800K記錄和我使用「,」作爲數據.. :(..反正我得到它的工作...我用StringTokenizer分裂..仍然im甚至沒有接近解決問題..我沒有將文件分割成1mb的每個..我使用AsyncTask並能夠插入5K記錄..緩衝區之後打破...這很奇怪,它只需要複製和創建數據庫很長。我還沒有開始在應用程序上工作...... :( – kthorat 2010-11-23 16:58:09