android SQLiteCantOpenDatabaseException: не удается открыть файл базы данных (код 14)

#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:

Я нашел несколько причин для моей версии этой ошибки.

  1. Не закрываются курсоры. Курсор является ресурсом с большим весом, и вы не можете открывать слишком много из них одновременно.

  2. Синхронизация ресурса базы данных. В реализации 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();