2010-05-22 106 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