DB 查询在 Android 上返回损坏的数据

发布于 2024-10-21 17:47:10 字数 1806 浏览 1 评论 0原文

我有一个带有示例表的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文