从 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的主要内容,如果未能解决你的问题,请参考以下文章
如何从数据库中检索所有表? (Android,SQLite)[重复]
从 Android Studio 中的 SQLite 数据库中以字符串形式检索数据
如何从列表视图中从 sqlite 检索数据单击并查看不同的活动 android studio