Почему файл SQLite существует, но openDatabase выдает ошибку? - PullRequest
1 голос
/ 15 июня 2019

Я знаю, что это повторный вопрос , но старые вопросы в Переполнение стека мне не помогают, потому что все изменилось.

a) Я скопировал мой SQLite файл your.db в мою папку asset (только для чтения) в Android Studio

b) В моем приложении я скопировал данные из моего ресурса во внутреннее хранилище следующим образом:

// Internal Storage Path: (/Data/User/0/*myapppath*/files)
val name="your.db"
val f = this.assets.open(name)
val SQLContent = f.bufferedReader().use{ it.readText()}
f.close()
val file = File(this.filesDir, name)
file.writeText(SQLContent)

c) Я проверил, если мой файлбыло действительно скопировано в мой Android сотовый телефон. Показанный ниже код отображает отображение OK в кнопке.Это так.

val file = File(this.filesDir, "your.db")
if (file.exists()) result="Ok" else result="Argh"I

d) Ниже кода для открытия моей базы данных (уже хранится во внутреннем хранилище).Однако выдает ошибку, поскольку система не нашла мою базу данных.

String DBPath  = file.getabsolutePath()
SQLiteDatabase db = SQLiteDatabase.openDatabase(DBPath,
    null, SQLiteDatabase.OPEN_READWRITE)

Я знаю, что рекомендуемое SQLite расположение базы данных - ...\databases, а не ...\files, но даже тогда, не имеет смысла выдавать ошибку, так как файл физически находится там.

ОБНОВЛЕНИЕ : Используя @ commonsware комментарий, я использовал Обозреватель файлов устройств .Итак, я заметил, что SQLiteDatabase.openDatabase ставит суффикс corrupt в имени файла. Однако ошибка:

Error Code : 1294 (SQLITE_CANTOPEN_ENOENT)
Caused By : Specified directory or database file does not exist.
    (unknown error (code 1294): Could not open database)

UPDATE 2

Использование @ commonsware принял ответ, я заменил код для копирования файлов на двоичную версию.

Копировать файл из ресурса во внутреннее хранилище:

val arq = this.assets.open(nome)
val file = File(this.filesDir, nome)
val saida = file.outputStream()
arq.copyTo(saida)
saida.close()
arq.close()

Теперь все работает гладко.Я открываю SQLite, запускаю запрос с курсором, сканирую курсор, печатаю записи, закрываю курсор и закрываю базу данных.Никаких дополнительных ошибок.

Когда я использовал Device File Explorer инструмент (Меню Просмотр , Инструмент Windows ), он показывает приватные файлы приложения.Когда я копирую файл SQLite обратно на мой компьютер (Использование copy as в контекстном меню правой кнопки) во время копирования остается ошибка.Я думаю, что эта опция пытается скопировать файл как текст, а не как двоичный файл.

Ответы [ 2 ]

3 голосов
/ 16 июня 2019

Я не заметил, что вы добавили свой код для копирования файлов в редактирование.

val SQLContent = f.bufferedReader().use{ it.readText()}

Базы данных SQLite - это двоичные файлы, а не текстовые. Используйте readBytes() и writeBytes(), а не readText() и writeText().

1 голос
/ 16 июня 2019

Активы всегда будут R / O, потому что они являются частью файла APK.Вот пример метода в Java, который возвращает дескриптор R / W (где DATABASE_FILENAME - имя файла для открытия):

private static SQLiteDatabase db;
private Context mContext;

@Nullable
public SQLiteDatabase getDatabase() {

    /* attempting to return early */
    if(db != null && db.isOpen()) {
        return db;
    } else {
        SQLiteDatabase db = null;
        File path = this.mContext.getDatabasePath(Constants.DATABASE_FILENAME);
        if (path.exists()) {
            try {
                db = SQLiteDatabase.openDatabase(path.getAbsolutePath(), null, SQLiteDatabase.OPEN_READWRITE);
            } catch (SQLiteCantOpenDatabaseException e) {
                Log.e(LOG_TAG, e.getMessage());
            }
        } else {
            Log.e(LOG_TAG, path.getAbsolutePath() + " does not exist.");
        }
        return db;
    }
}

(Обычный) ожидаемый каталог базы данных - /databases, а не /files.И если намеревается открыть R / O из активов (например, для импорта оттуда), то это должен быть флаг OPEN_READONLY ..., который, вероятно, является причиной для SQLITE_CANTOPEN_ENOENT в сочетании с флагом OPEN_READWRITE иРесурс R / O;Двойной вызов db.close() также стоит учитывать при импорте данных.Я просто использую db.execSQL() для вставки ... которая является надежной альтернативой возни с файлами базы данных - и можно даже вставить локализованные строки.Сбой двоичного копирования при локализации контента.

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