#java #android #sqlite #android-sqlite
#java #Android #sqlite #android-sqlite
Вопрос:
Я пытался исправить эту ошибку SQLiteCantOpenDatabaseException в течение последних 2 дней, но безрезультатно. Я выполняю итерацию по списку массивов размером 4750, и на каждой итерации я запрашиваю базу данных.
вот мой фрагмент кода:
/**
* This method generates edge sets from wifiList then updates the EdgeTable.
* Step1: Check if edge already exists in EdgeTable.
* Step2: if step1 is true then increment edge weight by 1
* otherwise insert a new edge into EdgeTable and set its default weight to 1
*
* @param wifiList List containing wifiIds(hash value of Access Points macAddresses)
* @param inervalID int intervall ID
**/
public static synchronized void updateEdgeTable(ArrayList<String> wifiList, int inervalID) {
ArrayList<ArrayList<String>> edgeList = new ArrayList<>();
//generating edge pairs from wifiList
for (int i = 0; i < wifiList.size() - 1; i ) {
for (int j = i 1; j < wifiList.size(); j ) {
edgeList.add(createEdge(wifiList.get(i), wifiList.get(j)));
}
} //[end 1st for loop]
// adding edges to the edge table
for (ArrayList<String> edge : edgeList) {
/*get edge from EdgeTable, cursor is empty if edge does not exist in the table*/
Cursor cursor = getRow(edge.get(0), edge.get(1), inervalID);
if (cursor != null amp;amp; cursor.moveToFirst()) {
/*if cursor is not empty, then edge already exists, hence increment the edge weight by 1*/
try {
updateEdgeWeight(edge.get(0), edge.get(1), cursor.getInt(cursor.getColumnIndex(EdgeTable.COLUMN_EdgeWeight)) 1, inervalID);
/* TODO: 10/18/16 : there is an error here : android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14),
(14) statement aborts at 18: [select * from EDGE_TABLE where INTERVAL_ID= 2 and SOURCE= "3Co/YY" and TARGET= "cinaVR"] unable to open database file */
} catch (Exception e) {
e.printStackTrace();
}
cursor.close();
} else {
/*if cursor is empty then edge does not exist, hence add new edge with default weight =1*/
EdgeTable entry = new EdgeTable();
entry.setIntervalID(inervalID);
entry.setSource(edge.get(0));
entry.setTarget(edge.get(1));
entry.setEdgeWeight(1);
EdgeRepository.insert(entry);
cursor.close();
} //[end if]
} //[end 2nd for loop]
} //[end of updateEdgeTable() method ]
/**
* This method performs the following select query:
* --> select * from EDGE_TABLE where INTERVAL_ID= intervalID and SOURCE= sourceNode and TARGET= targetNode
* Example: select * from EDGE_TABLE where INTERVAL_ID= 1 and SOURCE= "H0LaCI" and TARGET= "RZyhnJ"
* @param sourceNode the source node
* @param targetNode the target node
* @param inervalID interval ID
*@return A Cursor containing the query result
* */
public static synchronized Cursor getRow(String sourceNode, String targetNode, int inervalID) {
Cursor cursor = checkIfEdgeExist(sourceNode, targetNode, inervalID);
if (cursor.moveToFirst() == false) {
SQLiteDatabase db = DatabaseManager.getInstance().openDatabase();
cursor = db.rawQuery("select * from "
EdgeTable.TABLE " where "
EdgeTable.COLUMN_IntervalID "= " inervalID " and "
EdgeTable.COLUMN_Source "= " """ targetNode """ " and "
EdgeTable.COLUMN_Target "= " """ sourceNode """
, null);
}
DatabaseManager.getInstance().closeDatabase();
return cursor;
}
И ниже приведен мой логакт:
10-17 20:34:14.333 8028-8078 E/SQLiteLog: (14) cannot open file at line 30188 of [bda77dda96]
10-17 20:34:14.333 8028-8078 E/SQLiteLog: (14) os_unix.c:30188: (24) open(/data/user/0/lu.uni.myappmain.senspro/databases) -
10-17 20:34:14.340 8028-8078 E/SQLiteLog: (14) cannot open file at line 32456 of [bda77dda96]
10-17 20:34:14.341 8028-8078 E/SQLiteLog: (14) os_unix.c:32456: (24) open(/data/user/0/lu.uni.myappmain.senspro/databases/ActivityRecognitionDB.db-journal) -
10-17 20:34:14.341 8028-8078 E/SQLiteLog: (14) cannot open file at line 32456 of [bda77dda96]
10-17 20:34:14.341 8028-8078 E/SQLiteLog: (14) os_unix.c:32456: (24) open(/data/user/0/lu.uni.myappmain.senspro/databases/ActivityRecognitionDB.db-journal) -
10-17 20:34:14.341 8028-8078 E/SQLiteLog: (14) statement aborts at 18: [select * from EDGE_TABLE where INTERVAL_ID= 1 and SOURCE= "H0LaCI" and TARGET= "RZyhnJ"] unable to open database file
10-17 20:34:14.342 8028-8078 E/SQLiteQuery: exception: unable to open database file (code 14); query: select * from EDGE_TABLE where INTERVAL_ID= 1 and SOURCE= "H0LaCI" and TARGET= "RZyhnJ"
10-17 20:34:14.343 8028-8078 E/AndroidRuntime: FATAL EXCEPTION: Thread-4
Process: lu.uni.myappmain.senspro, PID: 8028
android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14)
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:845)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:219)
at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:258)
at lu.uni.myappmain.senspro.data.repository.EdgeRepository.updateEdgeTable(EdgeRepository.java:111)
at lu.uni.myappmain.senspro.MyMainService$3.run(MyMainService.java:365)
at java.lang.Thread.run(Thread.java:761)
Комментарии:
1.
at lu.uni.myappmain.senspro.data.repository.EdgeRepository.updateEdgeTable(EdgeRepository.java:111)
Что такое строка 111 из EdgeRepository.java ?
Ответ №1:
Я нашел несколько причин для моей версии этой ошибки.
-
Не закрываются курсоры. Курсор является ресурсом с большим весом, и вы не можете открывать слишком много из них одновременно.
-
Синхронизация ресурса базы данных. В реализации SQLiteDatabase отсутствует полная поддержка потоков.
Простейшее решение….
synchronized (DatabaseManager.getInstance())
Cursor cursor = checkIfEdgeExist(sourceNode, targetNode, inervalID);
if (cursor.moveToFirst() == false) {
SQLiteDatabase db = DatabaseManager.getInstance().openDatabase();
cursor = db.rawQuery("select * from "
EdgeTable.TABLE " where "
EdgeTable.COLUMN_IntervalID "= " inervalID " and "
EdgeTable.COLUMN_Source "= " """ targetNode """ " and "
EdgeTable.COLUMN_Target "= " """ sourceNode """
, null);
}
DatabaseManager.getInstance().closeDatabase();
}
У меня была база данных с использованием SQLiteOpenHelper.
В этот класс, который, как я убедился, был одноэлементным, я добавил следующий код…
private ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
public Lock readLock() {
return mLock.readLock();
}
public Lock writeLock() {
return mLock.writeLock();
}
Затем каждый раз, когда я использовал базу данных, я проверял доступ только для чтения или чтения-записи, вызывая соответствующим образом….
StorageContract.DbHelper helper = StorageContract.DbHelper .getInstance(this);
SQLiteDatabase db = helper.getReadableDatabase();
helper.readLock().lock();
try {
// do some read only operation on the database.
}
finally {
helper.readLock().unlock();
}
Ответ №2:
можете ли вы попробовать это? (в вашем методе курсора)
SQLiteDatabase db = this.getWritableDatabase();