存档/取消存档导致 initForReadingWithData 无法理解存档

发布于 2024-08-17 04:28:47 字数 2074 浏览 11 评论 0原文

我已经在 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 写入文件时尝试打开该文件,正确的列表编辑器显示错误:

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

plutil 也给出此错误:

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

I've implemented an save on applicationWillTerminate and load on applicationWillFinishLoading.
There is a complete object tree, all implement the NSCoding protocol and I've check the types I enter.

One of the classes also stores an NSMutableData to the NSKeyedArchive, which I suspect might break unarchiving occasionally. Weirdly enough, sometimes it works and sometimes it doesn't. I suspect some content in the NSMutableData will break the archiving.

I use encodeObject on all objects, except for the bools and int where I use the correct corresponding method (encodeBool:forKey: and encodeInt:forKey:)

To be more clear: the code really does work, sometimes is it able to rebuild a rather complete object graph, just not all the time.

The error message I get is:

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

Added: code which is failing, it an NSMutableData of 10+ MB

- (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;
}

When I remove the self.data encoding and decoding it always seem to work.
It also fails with smaller sized self.data. Doesn't seem size but content issue?

Tried to open the file when I did write the nsmutabledata to it, the propertly list editor displays the error:

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

plutil also gives this error:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自此以后,行同陌路 2024-08-24 04:28:47

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

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

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

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

希望这对某人有帮助!

FWIW I have also come across this problem and here is what I've found.

The bytes reported 0x62, 0x70, 0x6c, etc., are part of the magic string "bplist" at the start of a binary property list, which NSKeyedArchiver uses by default.

A binary property list stores metadata in a trailer (i.e. at the end of the data). So if it gets truncated, the entire plist becomes unreadable.

If you want to check whether that's what has happened to you, you can use NSPropertyListReader_binary1 from Cocotron (http://code.google.com/p/cocotron/source/browse/Foundation/NSPropertyList/) to see how the file format works.

Hope this helps someone!

一桥轻雨一伞开 2024-08-24 04:28:47

看来通过 NSMutableArray 存储超过大约 230000 字节将导致 NSKeyedArchiver 创建损坏的 plist 文件。

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

It seems that store more than around 230000 bytes via an NSMutableArray will cause the NSKeyedArchiver to create a broken plist file.

220000 works, 250000 didn't. Did search for the exact amount that is allowed.

爱的十字路口 2024-08-24 04:28:47

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

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

您可以参考这个有用指南更多案例。

For the bool and int, there are two methods: encodeBool:forKey: and encodeInt:forKey: (taken from the NSKeyedArchiver reference).

For the NSMutableData, you should archive them with encodeObjectForKey: and unarchive them with decodeObjectForKey:.

You can refer to this useful guide for more cases.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文