Создание базы данных приложения для Android с большим объемом данных - PullRequest
6 голосов
/ 23 декабря 2009

База данных моего приложения должна быть заполнена большим количеством данных, поэтому во время onCreate() это не только создание таблицы sql инструкции, там много вставок. Я выбрал решение сохранить все эти инструкции в файле sql, расположенном в res / raw и который загружен с Resources.openRawResource(id).

Работает хорошо, но я сталкиваюсь с проблемой кодировки, у меня есть некоторые акценты символы в файле sql, который появляется плохо в моем приложении. это мой код для этого:

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, чем большой static final String атрибут со всеми инструкциями sql?

Ответы [ 4 ]

8 голосов
/ 23 декабря 2009

Я думаю, что ваша проблема в этой строке:

return new String(buffer);

Вы конвертируете массив байтов в java.lang.String, но не говорите Java / Android, какую кодировку использовать. Таким образом, байты для ваших акцентированных символов не конвертируются правильно, так как используется неправильная кодировка.

Если вы используете конструктор String(byte[],<encoding>), вы можете указать кодировку вашего файла, и ваши символы будут преобразованы правильно.

4 голосов
/ 23 декабря 2009

Решение для файла SQL кажется идеальным, просто вам нужно убедиться, что файл сохранен в кодировке utf8, иначе все акцентированные символы будут потеряны. Если вы не хотите изменять кодировку файла, вам нужно передать дополнительный аргумент новому String(bytes, charset), определяющему кодировку файла.

Предпочитаете использовать файловые ресурсы вместо статической конечной строки, чтобы избежать загрузки всех ненужных байтов в память. В мобильных телефонах вы хотите сохранить всю возможную память!

1 голос
/ 19 марта 2012

Я использую другой подход: Вместо того, чтобы выполнять загрузки SQL-операторов (что займет много времени), я строю свою базу данных sqlite на рабочем столе, помещаю ее в папку активов, создаю пустую базу данных sqlite в Android и копирую базу данных из папки активов в папка базы данных. Это огромное увеличение скорости. Обратите внимание, вам нужно сначала создать пустую базу данных в Android, а затем скопировать и перезаписать ее. В противном случае Android не позволит вам записать базу данных в папку базы данных. В интернете есть несколько примеров. Кстати, кажется, этот подход работает лучше всего, если БД не имеет расширения файла.

0 голосов
/ 04 мая 2010

Похоже, вы передаете все свои SQL-операторы в одну строку. Это проблема, потому что execSQL ожидает «одного оператора, который не является запросом» (см. Документацию [здесь] [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}

Мои столбцы данных содержат текстовые фрагменты с новыми строками и точками с запятой, поэтому мне пришлось найти другой разделитель команд. Просто будьте креативны с split str: используйте то, что, как вы знаете, не существует в ваших данных.

НТН Херардо

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...