从 Android sqlite 数据库中检索大 blob

Posted

技术标签:

【中文标题】从 Android sqlite 数据库中检索大 blob【英文标题】:Retrieve large blob from Android sqlite database 【发布时间】:2012-09-24 20:59:49 【问题描述】:

我在 android 应用程序的 sqlite 数据库中存储了大块二进制数据(protobufs),却没有意识到 Android 的 Cursor 最多只能保存 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)。

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

【问题讨论】:

【参考方案1】:

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

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 stream I/O 函数或 C API 的普通查询函数,但在这种情况下这太复杂了。

【讨论】:

非常感谢!这真的很有帮助。我不知道 SQLite 的核心功能。完美运行! 你有什么有效的方法来添加这些块组成一个整体byte[] @KamranAhmed 你已经知道整个长度,所以分配一个大数组并复制块。 我想知道是否有比遍历每个字节更好的方法。感谢您及时的回复。 :) 你能提供一个带有步骤的例子吗,真的很有帮助【参考方案2】:

CL。只有blobsqlite4java 的库,该库使用对数据库的本机调用而不使用游标。以下是使用此库获取大 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();

【讨论】:

请注意,此代码会将整个 blob 存储在内存中。您可能没有足够的内存来存储它。除了columnBlob,您可以考虑columnStream,它允许您逐字节提取数据:almworks.com/sqlite4java/javadoc/com/almworks/sqlite4java/…

以上是关于从 Android sqlite 数据库中检索大 blob的主要内容,如果未能解决你的问题,请参考以下文章

从 SQLite 数据库 Android 中检索值

如何从数据库中检索所有表? (Android,SQLite)[重复]

从 Android Studio 中的 SQLite 数据库中以字符串形式检索数据

如何从列表视图中从 sqlite 检索数据单击并查看不同的活动 android studio

android Fragment - 我需要从 sqlite 检索数据并填充到 recylerview 的方法

无法从 SQLite 检索数据说 android (Eclipse) 中不存在该列