23

我在 Android 应用程序的 sqlite 数据库中存储了大块的二进制数据(protobufs),却没有意识到 AndroidCursor最多只能保存 1MB 的数据。我现在知道我应该将这些二进制 blob 存储在文件中,并且只引用 sqlite 数据库条目中的文件。

我需要升级数据库(该应用程序已经使用了一段时间)才能将这些二进制块移动到文件中。问题是某些用户的数据可能已经超过了 1MB 的限制,我无法从数据库中检索它(访问Cursor包含大 blob 的单行的结果会抛出IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialize before accessing data from it.

如何检索Cursor已存储在 sqlite 数据库中的大于 1MB 限制的二进制 blob?

4

2 回答 2

37

您可以分段读取大块。首先找出哪些需要这种治疗:

SELECT id, length(blobcolumn) FROM mytable WHERE length(blobcolumn) > 1000000

然后读取块substr

SELECT substr(blobcolumn,       1, 1000000) FROM mytable WHERE id = 123
SELECT substr(blobcolumn, 1000001, 1000000) FROM mytable WHERE id = 123
...

您还可以编译自己的 SQLite 副本并使用 NDK 访问BLOB 流 I/O函数或 C API 的普通查询函数,但在这种情况下这太复杂了。

于 2012-10-04T06:47:58.750 回答
0

CL。只有blob<5MB才能回答。如果您尝试将它与大于 5 兆字节的 blob 一起使用,您仍然会遇到异常。要获取大型 blob,您需要使用名为sqlite4java的库,该库使用对数据库的本机调用而不使用游标。以下是使用此库获取大 blob 的示例:

SQLiteConnection sqLiteConnection=null;
SQLiteStatement sqLiteStatement=null;
try
{
    File databaseFile = context.getDatabasePath("database.db");
    sqLiteConnection=new SQLiteConnection(databaseFile);
    sqLiteConnection.open();
    sqLiteStatement=sqLiteConnection.prepare("SELECT blob FROM table WHERE id=?");
    sqLiteStatement.bind(1, id);
    sqLiteStatement.step();
    byte[] blob=sqLiteStatement.columnBlob(0);
}
finally
{
    if(sqLiteStatement!=null)
        sqLiteStatement.dispose();
    if(sqLiteConnection!=null)
        sqLiteConnection.dispose();
}
于 2016-07-17T08:46:53.177 回答