用大量数据创建android app数据库

时间:2009-12-23 16:28:43

标签: java database android

我的应用程序的数据库需要填充大量数据, 所以在onCreate()期间,它不仅仅是一些create table sql 说明,有很多插入。我选择的解决方案是 将所有这些指令存储在res / raw中的sql文件中 已加载Resources.openRawResource(id)

它运作良好,但我面对编码问题,我有一些突出 sql文件中的caharacters在我的应用程序中看起来很糟糕。这个 我的代码是这样做的:

public String getFileContent(Resources resources, int rawId) throws
IOException
  {
    InputStream is = resources.openRawResource(rawId);
    int size = is.available();
    // Read the entire asset into a local byte buffer.
    byte[] buffer = new byte[size];
    is.read(buffer);
    is.close();
    // Convert the buffer into a string.
    return new String(buffer);
  }

public void onCreate(SQLiteDatabase db) {
   try {
        // get file content
        String sqlCode = getFileContent(mCtx.getResources(), R.raw.db_create);
        // execute code
        for (String sqlStatements : sqlCode.split(";"))
        {
            db.execSQL(sqlStatements);
        }

        Log.v("Creating database done.");
        } catch (IOException e) {
            // Should never happen!
            Log.e("Error reading sql file " + e.getMessage(), e);
            throw new RuntimeException(e);
        } catch (SQLException e) {
            Log.e("Error executing sql code " + e.getMessage(), e);
            throw new RuntimeException(e);
        }

我发现避免这种情况的解决方案是加载sql指令 从一个巨大的static final String而不是一个文件,所有 突出的角色显得很好。

但是加载sql指令比没有更优雅的方法 所有sql指令的static final String属性?

4 个答案:

答案 0 :(得分:8)

我认为你的问题就在这一行:

return new String(buffer);

您正在将字节数组转换为java.lang.String,但您没有告诉Java / Android使用的编码。因此,由于使用了错误的编码,因此重音字符的字节数无法正确转换。

如果您使用String(byte[],<encoding>)构造函数,则可以指定文件的编码,并且您的字符将被正确转换。

答案 1 :(得分:4)

SQL文件解决方案看起来很完美,只需要确保文件以utf8编码保存,否则所有突出的字符都将丢失。如果您不想更改文件的编码,则需要将额外的参数传递给定义文件编码的新String(bytes, charset)

更喜欢使用文件资源而不是静态最终字符串,以避免将所有不必要的字节加载到内存中。在手机中,您希望尽可能保存所有内存!

答案 2 :(得分:1)

我使用的是另一种方法: 而不是执行sql语句的加载(这需要很长时间才能完成),我在桌面上构建我的sqlite数据库,将它放在assets文件夹中,在android中创建一个空的sqlite数据库,并将db从assets文件夹复制到数据库夹。这是速度的巨大增长。注意,你需要先在android中创建一个空数据库,然后你可以复制并覆盖它。否则,Android将不允许您将db写入datbase文件夹。互联网上有几个例子。 顺便说一下,如果db没有文件扩展名,这种方法看起来效果最好。

答案 3 :(得分:-1)

看起来您将所有sql语句都传递到一个字符串中。这是一个问题,因为execSQL期望“单个语句不是查询”(参见文档[here] [1])。以下是一个有点丑陋但有效的解决方案。

我的所有sql语句都在这样的文件中:

  

INSERT INTO table1 VALUES(1,2,3);

     

INSERT INTO table1 VALUES(4,5,6);

     

INSERT INTO table1 VALUES(7,8,9);

注意文本之间的新行(分号后跟2个新行) 然后,我这样做:

String text = new String(buffer, "UTF-8");
for (String command : text.split(";\n\n")) { 
   try { command = command.trim(); 
   //Log.d(TAG, "command: " + command); 
   if (command.length() > 0) 
      db.execSQL(command.trim()); 
}
catch(Exception e) {do whatever you need here}

我的数据列包含带有新行和分号的文本blob,因此我必须找到不同的命令分隔符。确保使用split str获得创意:使用您知道的数据中不存在的内容。

HTH 赫拉尔

[1]:http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#execSQL(java.lang.String,java.lang.Object [])