DB 查询在 Android 上返回损坏的数据
我有一个带有示例表的 SQLite 数据库,该表存储在 assets/ 文件夹中。
该数据库包含一个表,其中一列是包含 BMP 图像的 BLOB。我可以在主机上使用 JDBC 完美地读取/写入该图像。
然后使用以下代码从模拟器访问数据:
final Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null, null, null);
if (cursor.moveToFirst()) {
byte[] icon = cursor.getBlob(cursor.getColumnIndex(SearchEngines.ICON));
// ...
但是尝试解码检索到的图像失败:
final Bitmap icon = BitmapFactory.decodeByteArray(icon , 0, icon.length);
我得到空结果并在日志中显示以下内容:
DEBUG/skia(374): --- decoder->decode returned false
在此之后,我将 blob 数组转储到文件中并与原始图像进行比较。这完全令人惊讶,因为唯一未发现的差异是检索到的 blob 中所有 0x00 字节都被替换为 0x25 0x30 序列:
0x00 -> 0x25 0x30 // %0
除此之外,所有数据都完好无损。到底是什么?
更新 1。 从模拟器中拉取数据库 (adb pull) 后,其中包含的数据已损坏(相同的 %0 符号)。因此,问题要么出在数据库本身,要么出在 query/getBlob 或其他数据库访问代码的实现/使用上。
更新2. *好像是错的* 据我了解,SQLite支持2种存储大对象的方式:TEXT和BLOB。 TEXT 列不包含 0x00 字节,并且在 BLOB 中 0x00 被转换为 %0(多么巧合!)。所以,看来我得到的是内部表示,而不是实际数据。
更新3.添加到DB的代码如下:
private void save(Connection conn, String id, String fileName) throws SQLException, IOException {
final String sql = "UPDATE " + TABLE_NAME + " SET " + BLOB_COLUMN_NAME + " = ? WHERE " + ID_COLUMN_NAME + " = ?";
System.out.println("Executing: " + sql);
final PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(2, Integer.valueOf(id));
File fBlob = new File(fileName);
FileInputStream is = new FileInputStream(fBlob);
byte[] bytes = new byte[(int) fBlob.length()];
int rc = is.read(bytes);
assert (rc == bytes.length);
System.out.println("Total size: " + rc);
pstmt.setBytes(1, bytes);
pstmt.execute();
}
I have an SQLite DB with a sample table, which is stored in the assets/ folder.
This DB contains a single table, one of the columns is BLOB containing a BMP image. I may read/write this image flawlessly using JDBC on the host machine.
Then the data is accessed from the emulator using the following code:
final Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null, null, null);
if (cursor.moveToFirst()) {
byte[] icon = cursor.getBlob(cursor.getColumnIndex(SearchEngines.ICON));
// ...
But the attempt to decode retreived image fails:
final Bitmap icon = BitmapFactory.decodeByteArray(icon , 0, icon.length);
I get null result and the following in the log:
DEBUG/skia(374): --- decoder->decode returned false
After this, I dumped the blob array into the file and compared with the original image. And it was a complete surprise, because the only uncovered difference was that all the 0x00 bytes were replaced with 0x25 0x30 sequences in the retreived blob:
0x00 -> 0x25 0x30 // %0
Besides that, all the data was intact. What the heck?
Update 1. After pulling the DB from the emulator (adb pull) the data it contains is corrupted (same %0 symbols). So, the problem is either in DB itself or implementation/usage of query/getBlob or other DB access code.
Update 2. *Seems that it's wrong* As far as I understand, SQLite supports 2 ways of storing large objects: TEXT and BLOB. TEXT columns don't contain 0x00 bytes, and in BLOBs 0x00 is translated into %0 (what a coincidence!). So, it seems that what I get is internal representation, not the actual data.
Update 3. Code for adding to DB is the following:
private void save(Connection conn, String id, String fileName) throws SQLException, IOException {
final String sql = "UPDATE " + TABLE_NAME + " SET " + BLOB_COLUMN_NAME + " = ? WHERE " + ID_COLUMN_NAME + " = ?";
System.out.println("Executing: " + sql);
final PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(2, Integer.valueOf(id));
File fBlob = new File(fileName);
FileInputStream is = new FileInputStream(fBlob);
byte[] bytes = new byte[(int) fBlob.length()];
int rc = is.read(bytes);
assert (rc == bytes.length);
System.out.println("Total size: " + rc);
pstmt.setBytes(1, bytes);
pstmt.execute();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论