【问题标题】:Archiving / Unarchiving results in initForReadingWithData incomprehensible archive归档/取消归档导致 initForReadingWithData 无法理解归档
【发布时间】:2010-01-08 09:53:47
【问题描述】:

我在applicationWillTerminate 上实现了保存并在applicationWillFinishLoading 上加载。 有一个完整的对象树,都实现了NSCoding协议,我已经检查了我输入的类型。

其中一个类还将NSMutableData 存储到NSKeyedArchive,我怀疑这可能会偶尔破坏取消归档。奇怪的是,有时它有效,有时则无效。我怀疑NSMutableData 中的某些内容会破坏存档。

我在所有对象上使用 encodeObject,除了 bools 和 int 我使用正确的对应方法(encodeBool:forKey:encodeInt:forKey:

更清楚一点:代码确实有效,有时它能够重建一个相当完整的对象图,但并非总是如此。

我得到的错误信息是:

initForReadingWithData incomprehensible archive 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30

添加:失败的代码,它是 10+ MB 的 NSMutableData

- (void)encodeWithCoder:(NSCoder*)encoder {
[encoder encodeObject:self.encodedMessage forKey:@"EncodedMessage"]; //NSData
[encoder encodeObject:self.data forKey:@"Data"]; //NSMutableData (10+MB)
[encoder encodeObject:self.header forKey:@"Header"]; //NSString
[encoder encodeObject:self.fileName forKey:@"FileName"]; //NSString
[encoder encodeInt:self.dataStartIndex forKey:@"DataStartIndex"]; //int
[encoder encodeInt:self.dataEndIndex forKey:@"DataEndIndex"]; //int
}

- (id)initWithCoder:(NSCoder*)decoder {
    if (self = [super init]) {
        self.encodedMessage = [decoder decodeObjectForKey:@"EncodedMessage"]; //NSData
        self.data = [decoder decodeObjectForKey:@"Data"]; //NSMutableData
        self.header = [decoder decodeObjectForKey:@"Header"]; //NSString
        self.fileName = [decoder decodeObjectForKey:@"FileName"]; //NSString
        self.dataStartIndex = [decoder decodeIntForKey:@"DataStartIndex"]; //int
        self.dataEndIndex = [decoder decodeIntForKey:@"DataEndIndex"]; //int
    }

    return self;
}

当我删除 self.data 编码和解码时,它似乎总是有效。 它也因较小的 self.data 而失败。似乎不是大小而是内容问题?

当我将 nsmutabledata 写入文件时尝试打开文件,propertly 列表编辑器显示错误:

"Conversion of string failed. The string is empty."

plutil 也给出了这个错误:

"$ plutil -lint nzbvortex.state nzbvortex.state: Conversion of string failed. The string is empty."

【问题讨论】:

  • 我也遇到过这个问题。错误信息与您的完全相同。我在NSFileCoordinator 读取块中使用NSKeyedUnarchiver 来取消归档由NSKeyedArchiver 在另一个线程中归档的数据。崩溃偶尔会发生,我在调试时无法重现它。你有解决办法吗?

标签: objective-c xcode macos archiving nscoding


【解决方案1】:

FWIW 我也遇到过这个问题,这就是我发现的。

报告的字节 0x62、0x70、0x6c 等是二进制属性列表开头的魔术字符串“bplist”的一部分,NSKeyedArchiver 默认使用该列表。

二进制属性列表将元数据存储在预告片中(即在数据末尾)。因此,如果它被截断,整个 plist 将变得不可读。

如果您想检查是否发生了这种情况,您可以使用 Cocotron (http://code.google.com/p/cocotron/source/browse/Foundation/NSPropertyList/) 的 NSPropertyListReader_binary1 来查看文件格式的工作原理。

希望这对某人有所帮助!

【讨论】:

  • 对我来说,确切的错误是数据被截断,就像你说的那样。你的答案应该是正确的。谢谢。
【解决方案2】:

似乎通过 NSMutableArray 存储超过 230000 个字节将导致 NSKeyedArchiver 创建损坏的 plist 文件。

220000 个有效,250000 个无效。是否搜索了允许的确切金额。

【讨论】:

  • 这是因为二进制 plist 被截断了。
【解决方案3】:

对于bool和int,有两种方法:encodeBool:forKey:encodeInt:forKey:(取自NSKeyedArchiver reference)。

对于 NSMutableData,您应该使用encodeObjectForKey: 将它们归档并使用decodeObjectForKey: 将它们取消归档。

更多案例可以参考这个useful guide

【讨论】:

  • 这正是我所做的。该代码有效,但并非总是如此。看起来特定内容似乎破坏了编码。
  • 您使用的是 XML 属性列表格式吗?如果是这样,您是否尝试过使用 PList 编辑器(在开发人员工具中)打开存档?
  • 在使用 NSKeyedArchiver 时,nsmutabledata 中存储的字节数似乎存在限制。问题已解决(实际上已绕过)。感谢您的帮助。
猜你喜欢
  • 2010-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多