【问题标题】:NSData is being truncated when stored in sqlite databaseNSData 存储在 sqlite 数据库中时被截断
【发布时间】:2011-01-27 23:12:14
【问题描述】:

我正在尝试将 NSMutableDictionaries 存储为 sqlite 中的 blob,首先通过 NSPropertyListSerialization 或 NSKeyedArchiver 将其转换为 NSData。

当我存储 blob 时,NSData 对象的长度为数千(KB 范围)。当我取回它时,它已被截断为 10 个字节。当我通过 SQLite 浏览器检查数据库时,大部分数据都消失了(如果我将字典存储为 NSPropertyListSerialization,我可以识别记录中的键,但字典的值消失了)。无论我是使用 NSPropertyListSerialization 还是 NSKeyedArchiver 来序列化我的数据,都会发生这种情况。

NSMutableDictionary* item = [items objectAtIndex:i];
NSData *dictionary  = [NSKeyedArchiver archivedDataWithRootObject:item];
sqlite3_bind_blob(  compiledStatement, 5, [dictionary bytes], [dictionary length], SQLITE_TRANSIENT);

这实际上是我的代码中的一个 sn-p,我在另一个相关问题中发布了完整部分。

Bulk inserts into sqlite db on the iphone

使用 gdb 或 NSLog 检查 [dictionary length] 的值会产生相同的结果:数据长度在 KB 范围内。

当我稍后检查检索数据时:

NSData* raw = [[NSData alloc] initWithBytes:sqlite3_column_blob(compiledStatement, 1) length:sqlite3_column_bytes(compiledStatement, 1)];
[raw release];

检查 [原始长度] 只给了我 10 个字节。对于我尝试存储在此列中的每个数据实例都是如此,无论它们的起始大小可能是什么,它们最终都会有 10 个字节。我的检索查询没有任何问题。我已经在命令行和 SQL 浏览器中运行它,并且我得到了正确的记录和列,但是存储在该特定列的记录中的数据不正确。

我的其余数据发生了什么变化?我使用 sqlite3_bind_blob 的方式有问题吗?我已经检查了 sqlite 文档以了解终止字符或最大大小限制。我的数据完全在 blob 条目的最大大小范围内,并且我找不到任何可能将我的数据缩小到大小的终端的信息。

【问题讨论】:

  • 我会检查 blob 的默认最大大小以及调整它的方法。那或者你正在某处缓冲数据,只有第一个块才能做到。
  • 没有“默认”最大尺寸,文档中的 AFAICT ......只有最大尺寸。这是巨大的。比我要存储的要大得多。我正在检查绑定调用之前的值,并且 NSData 的实例在那之前是活动的并且有效。在绑定调用期间,将 SQLITE_TRANSIENT 作为参数传递应该会复制我交给它的数据......这样以后丢失的数据不应该成为问题。
  • 这 10 个字节是什么?它实际上是对字典数据的截断吗?

标签: iphone objective-c sqlite nsdictionary nsdata


【解决方案1】:

您是否检查过该绑定的返回类型?有可能它返回一个错误代码(在这种情况下语句仍然可能会执行,只是不正确)。

作为一种解决方法,您是否尝试过创建 ZEROBLOB,然后使用 SQLite documentation 中描述的 BLOB I/O 例程对其进行写入?这将是我查看错误代码后尝试的下一件事。

【讨论】:

  • 它返回 SQLITE_OK。我会试一试 blob i/o,但是当您不以增量方式存储时,将 blob 提交到数据库是一种令人难以置信的迂回方式。
  • 另外,在更彻底地检查了这个方法之后,我担心开销。我必须先插入记录,然后通过获取 blob 句柄立即更新它?我想在 zeroblob 存在之前就对其进行写入是没有意义的,但这会占用我的事务更多时间,而且我非常担心性能。
  • zeroblob 只是一个占位符——它不会占用任何空间(或性能),直到您写入实际的 blob 数据。所以除非有问题,否则不要担心性能。
  • 我在这场疯狂的追逐中找到了肇事者……我取的是第 1 列的值,而不是第 0 列的值,第 0 列是包含我的数据的实际列。我假设由于将值绑定到您的查询从第 1 列开始,从查询结果中检索列也将从 1 开始。我的错误。无论如何感谢您的建议。知道我可以在不担心性能的情况下使用 zeroblob 可能会在将来的某个时候被证明是有用的。
【解决方案2】:

我在这场疯狂的追逐中找到了肇事者……我取的是第 1 列的值,而不是第 0 列的值,第 0 列是包含我的数据的实际列。我假设由于将值绑定到您的查询从第 1 列开始,从查询结果中检索列也将从 1 开始。我的错误。

每行 10 个字节实际上不是我的字典数据,而是我用来对结果进行排序的时间戳。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多