【问题标题】:Android sqlite unable to read after updating a blob更新 blob 后,Android sqlite 无法读取
【发布时间】:2018-11-11 02:07:11
【问题描述】:

我想在 SQLite 数据库中存储一个图像(大小约为 10MB)。为此,我创建了一个 DB 助手,一个 Dao。一切正常,我可以创建多条记录并毫无问题地读取它们,我什至可以毫无问题地更新最新记录中的 blob。
但是,如果我返回旧记录并更新 blob,我将无法再使用 blob 加载此记录。
我有一个显示所有记录的列表视图,为此我使用不返回 blob 的选择。此列表工作正常,但是当我单击列表中的某个项目时,我尝试使用 blob 加载记录,光标返回 0 行。

公共无效保存(比尔比尔){ ContentValues 值 = 新 ContentValues(); values.put(DatabaseHelper.BILL_NAME_COLUMN, aBill.getName()); values.put(DatabaseHelper.BILL_DUE_DATE_COLUMN, getContentValue(aBill.getDueDate())); values.put(DatabaseHelper.BILL_IMAGE_COLUMN, aBill.getImage()); if (!aBill.isPersistent()) { aBill.setId(database.insert(DatabaseHelper.BILL_TABLE, null, values)); abill.setpersistent(真实); } 别的 { database.update(DatabaseHelper.BILL_TABLE, values, DatabaseHelper.BILL_ID_COLUMN + "=?", new String[]{String.valueOf(aBill.getId())}); } } // 更新 blob 后失败 公共账单得到(长ID){ 光标 cursor = database.query(DatabaseHelper.BILL_TABLE, 新字符串 [] {DatabaseHelper.BILL_ID_COLUMN,DatabaseHelper.BILL_NAME_COLUMN,DatabaseHelper.BILL_DUE_DATE_COLUMN,DatabaseHelper.BILL_IMAGE_COLUMN},“id = ?”,新字符串 [] {String.valueOf(id)},空, 空,DatabaseHelper.BILL_DUE_DATE_COLUMN); 比尔比尔= null; while (cursor.moveToNext()) { 比尔=新比尔(); Bill.Setpersistent(True); bill.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.BILL_ID_COLUMN))); bill.setName(cursor.getString(cursor.getColumnIndex(DatabaseHelper.BILL_NAME_COLUMN))); bill.setDueDate(getDate(cursor.getString(cursor.getColumnIndex(DatabaseHelper.BILL_DUE_DATE_COLUMN)))); bill.setImage(cursor.getBlob(cursor.getColumnIndex(DatabaseHelper.BILL_IMAGE_COLUMN))); } cursor.close(); 返回账单; } //更新blob后工作正常 公共列表pindall(){ 列出账单 = new ArrayList(); 光标 cursor = database.query(DatabaseHelper.BILL_TABLE, 新字符串 [] {DatabaseHelper.BILL_ID_COLUMN,DatabaseHelper.BILL_NAME_COLUMN,DatabaseHelper.BILL_DUE_DATE_COLUMN},空,空,空, 空,DatabaseHelper.BILL_DUE_DATE_COLUMN); while (cursor.moveToNext()) { 比尔比尔=新比尔(); Bill.Setpersistent(True); bill.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.BILL_ID_COLUMN))); bill.setName(cursor.getString(cursor.getColumnIndex(DatabaseHelper.BILL_NAME_COLUMN))); bill.setDueDate(getDate(cursor.getString(cursor.getColumnIndex(DatabaseHelper.BILL_DUE_DATE_COLUMN)))); Bills.add(比尔); } cursor.close(); 退货; }

这是一个例外:

java.lang.IllegalStateException:无法从 CursorWindow 读取第 0 行第 0 列。确保在从光标访问数据之前正确初始化光标。 在 android.database.CursorWindow.nativeGetLong(本机方法) 在 android.database.CursorWindow.getLong(CursorWindow.java:511) 在 android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75) 在 net.rka.android.billreminder.BillDao.get(BillDao.java:106)

我怀疑连续更新 blob 会以某种方式损坏数据库。
有没有人遇到过类似的问题?如果有,你是怎么解决的?

【问题讨论】:

  • 你需要包含相关代码,考虑How do I ask a good question?
  • 日志中是否有堆栈跟踪,如果有,请添加。图片有多大?作为仅在读入游标时适用的限制,而不是在插入/更新列时,如果内存服务,CursorWindow 可以容纳 1 或 2m 的数据大小(因此通常只看到 BLOB)
  • 添加了堆栈跟踪。日志中没有以前的错误。正如我所说的,它工作正常,我可以毫无问题地添加具有相同大小图像的新记录。我可以打开它们。我什至可以一遍又一遍地更新最后一条记录并加载它们。但是当我更新以前的记录之一时,这些记录无法打开。光标不包含记录。
  • 尝试在while (cursor.moveToNext()) { .... 之前添加DatabaseUtils.dumpCursor(cursor);。输出将在日志中。还可以尝试从查询中省略图像,看看是否有效。
  • 10Mb 图像大小很可能会导致问题。最多大约和平均大约 100k 然后可以将图像存储在数据库中。再大一点,你应该真正将图像存储为文件并将路径存储在数据库中。

标签: android sqlite blob


【解决方案1】:

您的问题很可能是由于图像的大小和一个怪癖,为了更好的术语,您可以毫无问题地存储大型 BLOB,但由于 Android 的光标窗口的大小限制2m,您可能无法检索 BLOB。这有时会与一些 SQLiteDatabase/Cursor (在这种情况下为 Cursor getBlob() 或它的底层方法) 方法复杂化,这些方法基本上隐藏了底层故障,以提供通常更简单的开发体验。

如果您使用 SQLiteDatabase DatabaseUtils.dumpCursor 这可能会突出显示 SQLiteDatabase 查询便捷方法可能隐藏的问题。所以添加:-

DatabaseUtils.dumpCursor(cursor); //<<<< ADDED
while (cursor.moveToNext()) { ........

可能会提供线索。

我能想到 3 个选项:-

  1. 不是将文件存储为 BLOBS,而是将文件存储为磁盘上的文件并将路径存储在数据库中。
  2. 显着减小图像的大小。
  3. 研究使用 C++ 和本机 SQLIte3 库将 BLOBS 检索到适当大小的容器中。

也许有一些库可以做到这一点。但是,我不记得有人提到过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 2017-06-10
    • 2015-01-17
    • 1970-01-01
    相关资源
    最近更新 更多