android java.lang.IllegalStateException:无法从 CursorWindow 读取第 0 行,第 0 列

Posted

技术标签:

【中文标题】android java.lang.IllegalStateException:无法从 CursorWindow 读取第 0 行,第 0 列【英文标题】:android java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow 【发布时间】:2014-02-21 08:14:03 【问题描述】:

我正在开发一个应用程序,它下载一些文件并将它们的文本保存在 file_content 字段到数据库中。文件大小可以从几 KB 到 10 MB 不等。该应用程序适用于所有尺寸,同时保存。对长 file_content 记录使用 select 语句时会出现问题。它给了

java.lang.IllegalStateException: 无法从 CursorWindow 读取第 0 行第 0 列

在获取此类行时。字段内容大小是否有任何限制?如果是这样,那么为什么它让我们在检索时保存并给出错误? 这是我截取的获取行的代码:

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)

【问题讨论】:

我已经向 Google 报告了这张票,这是一个糟糕的 API,允许开发人员陷入这种情况。对此问题加注星标并发表评论,以获得 Google 的关注以解决该问题:issuetracker.google.com/issues/145977220 【参考方案1】:

01-29 13:41:56.520:W/CursorWindow(4121):窗口已满:请求分配 5140987 字节,可用空间 2096617 字节,窗口大小 2097152 字节

Android SQLite 在光标窗口中返回最大大小为 2MB 的行,由 config_cursorWindowSize 指定。如果您的行超过此限制,您将收到此错误。

无论如何,在 sqlite 数据库中存储大数据并不是一个好主意。将文件存储在文件系统中,将路径存储在数据库中。

【讨论】:

是的,我知道在数据库中存储大文件不是一个好主意,但我必须稍后对下载的文件执行不同的搜索操作。所以内容需要在数据库中。 您必须为此目的对数据进行索引。 哇终于在这里找到了我的问题的答案!我的数据库中有一个大的 JSON 字符串——难怪我无法获取它。可能大于 2MB。不错。 @MIkkaMarmik 你不知道。您应该将内容存储在文件系统上并将内容的路径保存在数据库中,而不是存储内容本身 奇怪的是,android 允许您在没有任何大小限制的情况下序列化数据。现在,由于我的应用程序中的一个错误,对于某些用户来说,其中一行是臃肿的,无法读取!有没有办法读取一次可能会带来一些性能开销,以便修复它?【参考方案2】:

在使用 React Native 的情况下,它适用于我:

MainApplication.javaonCreate()末尾添加这段代码

try 
  Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize");
  field.setAccessible(true);
  field.set(null, 100 * 1024 * 1024); //100MB
   catch (Exception e) 
 if (BuildConfig.DEBUG) 
  e.printStackTrace();
  
  

同时在 MainApplication.java 上导入这些

import android.database.CursorWindow;
import java.lang.reflect.Field;

【讨论】:

【参考方案3】:

如果您想将图像保存为字节,另一种方法是在压缩位图时将质量设置为 0。

【讨论】:

以上是关于android java.lang.IllegalStateException:无法从 CursorWindow 读取第 0 行,第 0 列的主要内容,如果未能解决你的问题,请参考以下文章

解决:Retrofit请求返回: Expected a string but was BEGIN_OBJECT at line 1 column 4832 path $

解决:Retrofit请求返回: Expected a string but was BEGIN_OBJECT at line 1 column 4832 path $

解决:Retrofit请求返回: Expected a string but was BEGIN_OBJECT at line 1 column 4832 path $

解决:Retrofit请求返回: Expected a string but was BEGIN_OBJECT at line 1 column 4832 path $

Android逆向系列文章— Android基础逆向

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )