android java.lang.IllegalStateException: не удалось прочитать строку 0, столбец 0 из CursorWindow

Я разрабатываю приложение, которое загружает некоторые файлы и сохраняет их текст в поле file_content в базе данных. Размеры файлов могут варьироваться от нескольких КБ до 10 МБ. Приложение работает для всех размеров при сохранении. Проблема возникает при использовании оператора select для длинных записей file_content. Это дает

java.lang.IllegalStateException: не удалось прочитать строку 0, столбец 0 из CursorWindow

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

public String getFileContent(MyFile gc) {
        if(!isDBOpen()) {
            open();
        }
        try {
            String mQuery = "SELECT * FROM " + DBOpenHelper.TABLE_SAVED_FILES + " WHERE " + DBOpenHelper.COLUMN_ID + " = " + gc.id;
            Cursor mCursor = database.rawQuery(mQuery, null);
            if(mCursor.getCount() <= 0) {
                return null;
            }
            if(mCursor.moveToFirst()) {
                return getCursorRowContent(mCursor);
            }
        } catch (Exception e) {
            e.getMessage();
        }
        return null;
    }

    private String getCursorRowContent(Cursor mCursor) throws Exception {
        return mCursor.getString(mCursor.getColumnIndex(DBOpenHelper.COLUMN_FILE_CONTENT));
    }

Есть идеи, что происходит? Я тестировал его на 2-3 устройствах.

Вывод Logcat:

01-29 13:41:56.520: W/CursorWindow(4121): Window is full: requested allocation 5140987 bytes, free space 2096617 bytes, window size 2097152 bytes
01-29 13:41:56.520: E/CursorWindow(4121): Failed to read row 0, column 0 from a CursorWindow which has 0 rows, 9 columns.

01-29 13:43:30.932: W/System.err(4121): java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it. 
01-29 13:43:30.932: W/System.err(4121):     at android.database.CursorWindow.nativeGetLong(Native Method) 
01-29 13:43:30.932: W/System.err(4121):     at android.database.CursorWindow.getLong(CursorWindow.java:507) 
01-29 13:43:30.932: W/System.err(4121):     at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75) 
01-29 13:43:30.936: W/System.err(4121):     at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:220) 
01-29 13:43:30.936: W/System.err(4121):     at android.database.AbstractCursor.moveToNext(AbstractCursor.java:245) 
01-29 13:43:30.940: W/System.err(4121):     at com.nxb.cachehead.bl.PocketQueryDataSource.getGeoCacheContent(PocketQueryDataSource.java:97) 01-29 13:43:30.940: W/System.err(4121):     at com.nxb.cachehead.bl.GPXFileCopyAsyncTask.doInBackground(GPXFileCopyAsyncTask.java:27) 
01-29 13:43:30.940: W/System.err(4121):     at com.nxb.cachehead.bl.GPXFileCopyAsyncTask.doInBackground(GPXFileCopyAsyncTask.java:1) 
01-29 13:43:30.940: W/System.err(4121):     at android.os.AsyncTask$2.call(AsyncTask.java:287) 
01-29 13:43:30.944: W/System.err(4121):     at java.util.concurrent.FutureTask.run(FutureTask.java:234) 
01-29 13:43:30.944: W/System.err(4121):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
01-29 13:43:30.948: W/System.err(4121):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
01-29 13:43:30.948: W/System.err(4121):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
01-29 13:43:30.948: W/System.err(4121):     at java.lang.Thread.run(Thread.java:856)

person Khawar Raza    schedule 29.01.2014    source источник
comment
Я сообщил об этом тикете в Google, это плохой API, который позволяет разработчикам попасть в такую ​​ситуацию. Пометьте и прокомментируйте эту проблему, чтобы привлечь внимание Google к ее решению: issueetracker.google.com/issues/145977220   -  person satur9nine    schedule 10.12.2019


Ответы (2)


01-29 13:41: 56.520: W / CursorWindow (4121): Окно заполнено: запрошенное выделение 5140987 байтов, свободное пространство 2096617 байтов, размер окна 2097152 байта

Android SQLite возвращает строки в окнах курсора, максимальный размер которых составляет 2 МБ, как указано в _ 1_. Если ваша строка превышает этот предел, вы получите эту ошибку.

В любом случае хранить большие данные в базе данных sqlite не рекомендуется. Хранить файлы в файловой системе и пути в базе данных.

person laalto    schedule 29.01.2014
comment
Да, я знаю, что хранить большие файлы в базе данных - не лучшая идея, но позже мне придется выполнять различные операции поиска с загруженными файлами. Значит, контент должен быть в базе данных. - person Khawar Raza; 29.01.2014
comment
Вам нужно будет проиндексировать данные для таких целей. - person laalto; 29.01.2014
comment
вау наконец-то нашел здесь ответ на мою проблему! У меня в базе данных есть большая строка JSON - неудивительно, что я не могу ее получить. вероятно больше 2 МБ. отлично. - person james; 19.12.2014
comment
@binnyb Как можно добиться, чтобы в базе данных можно было хранить большой json размером более 2 МБ и выбрать его? - person MIkka Marmik; 31.03.2017
comment
@MIkkaMarmik, ты не знаешь. Вы должны хранить содержимое в файловой системе и сохранять путь к содержимому в базе данных, а не хранить само содержимое - person james; 31.03.2017
comment
Странно, что Android позволяет сериализовать данные без каких-либо ограничений по размеру. Теперь из-за ошибки в моем приложении для некоторых пользователей одна из строк раздута и не может быть прочитана! Есть ли способ прочитать его один раз, возможно, с некоторыми накладными расходами, чтобы исправить это? - person adarsh; 15.05.2017
comment
Омг, я так и не смог найти это, слишком много документации, чтобы читать ... Большое спасибо. - person IgniteCoders; 04.04.2018
comment
какие-то исправления еще ?? - person AmiNadimi; 07.08.2018
comment
Возможно, вы можете использовать @ColumnInfo(typeAffinity = ColumnInfo.BLOB) в поле изображения и сохранить его как ByteArray - person Edward van Raak; 09.04.2019
comment
Почему Android API позволяет записать строку размером 2 МБ в базу данных, но затем выдает сбой приложения с IllegalStateException, когда вы пытаетесь ее прочитать? Sqlite прекрасно справляется с этим, но оболочка Android - нет. Неработающий API. - person satur9nine; 10.12.2019

Если вы хотите сохранить изображения в байтах, другой способ сделать это - при сжатии растрового изображения установить качество на 0.

person alibabaei12    schedule 09.11.2018