#java #android-sqlite
Вопрос:
Это работало с использованием жестко закодированного пути. Мой путь неверен? Это мой код для получения пути
public class DatabaseAssets extends SQLiteOpenHelper {
private static String dbName = "questions.db";
Context context;
File dbFile;
public DatabaseAssets(Context context) {
super(context, "questions.db", null, 1);
this.context = context;
File DB_PATH = context.getDatabasePath(dbName);
String db = DB_PATH.getAbsolutePath();
dbFile= new File(db "questions.db");
}
Это мой код getWritableDatabase и getReadableDatabase.
@Override
public synchronized SQLiteDatabase getWritableDatabase() {
if(!dbFile.exists()){
SQLiteDatabase db = super.getWritableDatabase();
copyDataBase(db.getPath());
}
return super.getWritableDatabase();
}
@Override
public synchronized SQLiteDatabase getReadableDatabase() {
if(!dbFile.exists()){
SQLiteDatabase db = super.getReadableDatabase();
copyDataBase(db.getPath());
}
return super.getReadableDatabase();
}
Это мой код для копирования, но я не думаю, что в этом проблема.
private void copyDataBase(String dbPath){
try{
InputStream assestDB = context.getAssets().open("databases/" "questions.db");
OutputStream appDB = new FileOutputStream(dbPath,false);
byte[] buffer = new byte[1024];
int length;
while ((length = assestDB.read(buffer)) > 0) {
appDB.write(buffer, 0, length);
}
appDB.flush();
appDB.close();
assestDB.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
Комментарии:
1. При использовании относительного пути вы должны убедиться, что используете также правильный рабочий путь для своей программы.
Ответ №1:
Я считаю, что ваша проблема, потому что вы используете SQLiteDatabase db = super.getReadableDatabase();
или getWritableDatabase (не имеет значения, какой), а также, что вы добавите имя базы данных к базе данных, имя (и, таким образом, путь будет данных/данных/<the_package_name>/базы данных/вопросы.dbquestions.дБ вместо данных/данных/<the_package_name>/базы данных/вопросы.дБ) :-
Вы можете устранить проблему с именем пути, используя либо :-
public DatabaseAssets(Context context) {
super(context, "questions.db", null, 1);
this.context = context;
File DB_PATH = context.getDatabasePath(dbName);
String db = DB_PATH.getAbsolutePath();
//dbFile = new File(db "questions.db");
// path will be data/data/<the_package_name>/database/questions.dbquestions.db
dbFile = new File(db);
}
или :-
public DatabaseAssets(Context context) {
super(context,dbName,null,1);
this.context = context;
dbFile = context.getDatabasePath(dbName);
}
Что касается первой упомянутой проблемы, получение доступной для записи или чтения базы данных исторически использовалось для обхода проблемы, заключающейся в том, что копия ресурса не удалась бы (из-за отсутствия каталога баз данных при установке приложения). Это создает базу данных, которая затем переопределяется ТОЛЬКО для создания каталога баз данных.
В более поздних версиях Android режим по умолчанию теперь WAL (Ведение журнала с опережением записи), раньше это был журнал. С помощью WAL изменения в базе данных записываются в файл WAL. Копирование ресурса приведет к копированию только базы данных, а не файла WAL. При открытии базы данных обнаруживается проблема (часть WAL не совпадает с базой данных), и чрезмерно добрый Android API создает новую пустую базу данных вместо сбоя.
Чтобы избежать этой проблемы, вы можете создать отсутствующий каталог (что на самом деле более эффективно в любом случае). Так что вместо :-
if(!dbFile.exists()){
SQLiteDatabase db = super.getWritableDatabase();
copyDataBase(db.getPath());
}
Воспользуйся :-
if(!dbFile.exists()){
if (!dbFile.getParentFile().exists) {
dbfile.mkdirs()
}
copyDataBase(dbFile.getPath());
}
Комментарии:
1. Спасибо, но что такое «db» в базе данных,getPath() сейчас? поскольку getWritable не должен использоваться здесь?
2. упс, моя ошибка должна быть
dbFile.getPath()
изменена соответствующим образом. Однако getReadableDatabase вернет (во всех ситуациях, кроме ОЧЕНЬ ограниченных) доступную для записи базу данных. см. developer.android.com/reference/android/database/sqlite/. …