NSKeyedUnarchiver 发现损坏的数据
NSKeyedUnarchiver finds corrupted data
我有一个存档程序和一个解档程序可以协同工作。
第二个程序的运行结果表明,尽管两个对象(myFoo1)中的一个对象(myFoo1)已很好地归档、存储并稍后取消归档,但另一个(myBook)似乎无法正确取消归档。我只是不知道在似乎损坏了部分原始数据的归档 and/or 解档过程中发生了什么。我已仔细确保编码密钥与解码密钥相同,但程序仍然存在。
归档程序代码:
#import <Foundation/Foundation.h>
@interface Foo : NSObject <NSCoding>
@property (copy, nonatomic) NSString * strVal;
@property int intVal;
@property float floatVal;
-(void) display;
@end
#import "Foo.h"
@implementation Foo
@synthesize strVal, intVal, floatVal;
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: strVal forKey: @"FoostrVal"];
[aCoder encodeInt: intVal forKey: @"FoointVal"];
[aCoder encodeFloat: floatVal forKey: @"FoofloatVal"];
// NSLog (@"Foo encodeWithCoder called"); called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
strVal = [aDecoder decodeObjectForKey: @"FoostrVal"];
intVal = [aDecoder decodeIntForKey: @"FoointVal"];
floatVal = [aDecoder decodeFloatForKey: @"FoofloatVal"];
// NSLog (@"Foo initWithCoder called"); not called
return self;
}
-(void) display
{
NSLog (@"%@ %i %g", strVal, intVal, floatVal);
}
@end
#import <Foundation/Foundation.h>
@interface AddressCard : NSObject <NSCoding>
@property (nonatomic, copy) NSString * name, * email;
-(instancetype) initWithName: (NSString *) theName andEmail: (NSString *) theEmail;
-(void) showCard;
@end
#import "AddressCard.h"
@implementation AddressCard
@synthesize name, email;
-(instancetype) initWithName: (NSString *) theName andEmail: (NSString *) theEmail
{
self = [super init];
if (self) {
self.name = [NSString stringWithString: theName];
self.email = [NSString stringWithString: theEmail];
}
return self;
}
-(instancetype) init
{
return [self initWithName: @"NoName" andEmail: @"NoEmail"];
}
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: name forKey: @"AddrCardName"];
[aCoder encodeObject: email forKey: @"AddrCardEmail"];
// NSLog (@"AddressCard encodeWithCoder called"); called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
[aDecoder decodeObjectForKey: @"AddrCardName"];
[aDecoder decodeObjectForKey: @"AddrCardEmail"];
// NSLog (@"AddressCard initWithCoder called"); not called
return self;
}
-(void) showCard
{
NSLog (@"%-20s%-40s", [name UTF8String], [email UTF8String]);
}
@end
#import "AddressCard.h"
@interface AddressBook : NSObject <NSCoding>
@property (nonatomic, copy) NSString * title;
@property (nonatomic, strong) NSMutableArray * book;
-(instancetype) initWithTitle: (NSString *) title;
-(void) addCard: (AddressCard *) card;
-(void) list;
@end
#import "AddressBook.h"
@implementation AddressBook
@synthesize title, book;
-(instancetype) initWithTitle: (NSString *) theTitle
{
self = [super init];
if (self) {
title = [NSString stringWithString: theTitle];
book = [NSMutableArray array];
}
return self;
}
-(instancetype) init
{
return [self initWithTitle: @"NoTitle"];
}
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: title forKey: @"AddrBookTitle"];
[aCoder encodeObject: book forKey: @"AddrBookBook"];
// NSLog (@"AddressBook encodeWithCoder called"); called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
[aDecoder decodeObjectForKey: @"AddrBookTitle"];
[aDecoder decodeObjectForKey: @"AddrBookBook"];
// NSLog (@"AddressBook initWithCoder called"); not called
return self;
}
-(void) addCard: (AddressCard *) card
{
if ([book containsObject: card] == YES)
NSLog (@"The card already exists in %@", title);
else
[book addObject: card];
}
-(void) list
{
for (AddressCard * card in book)
[card showCard];
}
@end
#import "AddressBook.h"
#import "Foo.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Foo * myFoo1 = [[Foo alloc] init];
NSMutableData * dataArea;
NSKeyedArchiver * archiver;
AddressBook * myBook = [[AddressBook alloc] initWithTitle: @"Steve's Address Book"];
NSString * aName = @"Julia Kochan";
NSString * aEmail = @"jewls337@axlc.com";
NSString * bName = @"Tony Iannino";
NSString * bEmail = @"tony.iannino@tecfitness.com";
NSString * cName = @"Stephen Kochan";
NSString * cEmail = @"steve@steve_kochan.com";
NSString * dName = @"Jamie Baker";
NSString * dEmail = @"jbaker@hitmail.com";
NSString * filePath = @"addrbook.arch";
AddressCard * card1 = [[AddressCard alloc] initWithName: aName andEmail: aEmail];
AddressCard * card2 = [[AddressCard alloc] initWithName: bName andEmail: bEmail];
AddressCard * card3 = [[AddressCard alloc] initWithName: cName andEmail: cEmail];
AddressCard * card4 = [[AddressCard alloc] initWithName: dName andEmail: dEmail];
// Add some cards to the address book
[myBook addCard: card1];
[myBook addCard: card2];
[myBook addCard: card3];
[myBook addCard: card4];
myFoo1.strVal = @"This is the string";
myFoo1.intVal = 12345;
myFoo1.floatVal = 99.8;
// Set up a data area and connect it to an NSKeyedArchiver object
dataArea = [NSMutableData data];
archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: dataArea];
// Now we can begin to archive objects
[archiver encodeObject: myBook forKey: @"myaddrbook"];
[archiver encodeObject: myFoo1 forKey: @"myfoo1"];
[archiver finishEncoding];
// Write the archived data area to a file
if ([dataArea writeToFile: filePath atomically: YES] == NO)
NSLog (@"Archiving failed!");
NSLog (@"All operations successful!");
}
return 0;
}
解压程序代码:
#import <Foundation/Foundation.h>
@interface Foo : NSObject <NSCoding>
@property (copy, nonatomic) NSString * strVal;
@property int intVal;
@property float floatVal;
-(void) display;
@end
#import "Foo.h"
@implementation Foo
@synthesize strVal, intVal, floatVal;
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: strVal forKey: @"FoostrVal"];
[aCoder encodeInt: intVal forKey: @"FoointVal"];
[aCoder encodeFloat: floatVal forKey: @"FoofloatVal"];
// NSLog (@"Foo encodeWithCoder called"); not called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
strVal = [aDecoder decodeObjectForKey: @"FoostrVal"];
intVal = [aDecoder decodeIntForKey: @"FoointVal"];
floatVal = [aDecoder decodeFloatForKey: @"FoofloatVal"];
// NSLog (@"Foo initWithCoder called"); called
return self;
}
-(void) display
{
NSLog (@"%@\n%i\n%g", strVal, intVal, floatVal);
}
@end
#import <Foundation/Foundation.h>
@interface AddressCard : NSObject <NSCoding>
@property (nonatomic, copy) NSString * name, * email;
-(instancetype) initWithName: (NSString *) theName andEmail: (NSString *) theEmail;
-(void) showCard;
@end
#import "AddressCard.h"
@implementation AddressCard
@synthesize name, email;
-(instancetype) initWithName: (NSString *) theName andEmail: (NSString *) theEmail
{
self = [super init];
if (self) {
self.name = [NSString stringWithString: theName];
self.email = [NSString stringWithString: theEmail];
}
return self;
}
-(instancetype) init
{
return [self initWithName: @"NoName" andEmail: @"NoEmail"];
}
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: name forKey: @"AddrCardName"];
[aCoder encodeObject: email forKey: @"AddrCardEmail"];
// NSLog (@"AddressCard encodeWithCoder called"); not called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
[aDecoder decodeObjectForKey: @"AddrCardName"];
[aDecoder decodeObjectForKey: @"AddrCardEmail"];
// NSLog (@"AddressCard initWithCoder called"); called
return self;
}
-(void) showCard
{
NSLog (@"%-20s%-40s", [name UTF8String], [email UTF8String]);
}
@end
#import "AddressCard.h"
@interface AddressBook : NSObject <NSCoding>
@property (nonatomic, copy) NSString * title;
@property (nonatomic, strong) NSMutableArray * book;
-(instancetype) initWithTitle: (NSString *) title;
-(void) addCard: (AddressCard *) card;
-(void) list;
@end
#import "AddressBook.h"
@implementation AddressBook
@synthesize title, book;
-(instancetype) initWithTitle: (NSString *) theTitle
{
self = [super init];
if (self) {
title = [NSString stringWithString: theTitle];
book = [NSMutableArray array];
}
return self;
}
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: title forKey: @"AddrBookTitle"];
[aCoder encodeObject: book forKey: @"AddrBookBook"];
// NSLog (@"AddressBook encodeWithCoder called"); not called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
[aDecoder decodeObjectForKey: @"AddrBookTitle"];
[aDecoder decodeObjectForKey: @"AddrBookBook"];
// NSLog (@"AddressBook initWithCoder called"); called
return self;
}
-(void) addCard: (AddressCard *) card
{
if ([book containsObject: card] == YES)
NSLog (@"The card already exists in %@", title);
else
[book addObject: card];
}
-(void) list
{
for (AddressCard * card in book)
[card showCard];
}
@end
#import "AddressBook.h"
#import "Foo.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSData * dataArea;
NSKeyedUnarchiver * unarchiver;
Foo * myFoo1;
AddressBook * myBook;
NSString * filePath = @"addrbook.arch";
// Read in the archive and connect an
// NSkeyedUnarchiver object to it
dataArea = [NSData dataWithContentsOfFile: filePath];
if (!dataArea) {
NSLog (@"Can't read back archive file!");
return 1;
}
unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: dataArea];
// Decode the objects we previously stored in the archive
myBook = [unarchiver decodeObjectForKey: @"myaddrbook"];
myFoo1 = [unarchiver decodeObjectForKey: @"myfoo1"];
[unarchiver finishDecoding];
// Verify that the resote was successful
if (myBook != nil) {
if ([myBook.book count] == 0)
NSLog (@"Data corrupted in myBook!");
else
[myBook list];
}
else
NSLog (@"Load myBook failed!");
if (myFoo1 != nil)
[myFoo1 display];
else
NSLog (@"Load myFoo1 failed!");
}
return 0;
}
运行 以上解档程序的结果:
myBook 中的数据已损坏!
这是字符串
12345
99.8
程序以退出代码结束:0
这里有两个问题:您的 AddressBook
和 AddressCard
-initWithCoder:
实现都不是
- 呼叫
self = [super init]
。这不是问题的根本原因,但肯定是不正确的
- 也不会将解码结果分配给您的任何属性。您解码
AddrBookBook
,但永远不会将其分配给 self.book
;因此,myBook.book == nil
,[myBook.book count] == 0
。所有解码调用都应显示为 myIvar = [aDecoder decodeObjectForKey:...]
我有一个存档程序和一个解档程序可以协同工作。
第二个程序的运行结果表明,尽管两个对象(myFoo1)中的一个对象(myFoo1)已很好地归档、存储并稍后取消归档,但另一个(myBook)似乎无法正确取消归档。我只是不知道在似乎损坏了部分原始数据的归档 and/or 解档过程中发生了什么。我已仔细确保编码密钥与解码密钥相同,但程序仍然存在。
归档程序代码:
#import <Foundation/Foundation.h>
@interface Foo : NSObject <NSCoding>
@property (copy, nonatomic) NSString * strVal;
@property int intVal;
@property float floatVal;
-(void) display;
@end
#import "Foo.h"
@implementation Foo
@synthesize strVal, intVal, floatVal;
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: strVal forKey: @"FoostrVal"];
[aCoder encodeInt: intVal forKey: @"FoointVal"];
[aCoder encodeFloat: floatVal forKey: @"FoofloatVal"];
// NSLog (@"Foo encodeWithCoder called"); called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
strVal = [aDecoder decodeObjectForKey: @"FoostrVal"];
intVal = [aDecoder decodeIntForKey: @"FoointVal"];
floatVal = [aDecoder decodeFloatForKey: @"FoofloatVal"];
// NSLog (@"Foo initWithCoder called"); not called
return self;
}
-(void) display
{
NSLog (@"%@ %i %g", strVal, intVal, floatVal);
}
@end
#import <Foundation/Foundation.h>
@interface AddressCard : NSObject <NSCoding>
@property (nonatomic, copy) NSString * name, * email;
-(instancetype) initWithName: (NSString *) theName andEmail: (NSString *) theEmail;
-(void) showCard;
@end
#import "AddressCard.h"
@implementation AddressCard
@synthesize name, email;
-(instancetype) initWithName: (NSString *) theName andEmail: (NSString *) theEmail
{
self = [super init];
if (self) {
self.name = [NSString stringWithString: theName];
self.email = [NSString stringWithString: theEmail];
}
return self;
}
-(instancetype) init
{
return [self initWithName: @"NoName" andEmail: @"NoEmail"];
}
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: name forKey: @"AddrCardName"];
[aCoder encodeObject: email forKey: @"AddrCardEmail"];
// NSLog (@"AddressCard encodeWithCoder called"); called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
[aDecoder decodeObjectForKey: @"AddrCardName"];
[aDecoder decodeObjectForKey: @"AddrCardEmail"];
// NSLog (@"AddressCard initWithCoder called"); not called
return self;
}
-(void) showCard
{
NSLog (@"%-20s%-40s", [name UTF8String], [email UTF8String]);
}
@end
#import "AddressCard.h"
@interface AddressBook : NSObject <NSCoding>
@property (nonatomic, copy) NSString * title;
@property (nonatomic, strong) NSMutableArray * book;
-(instancetype) initWithTitle: (NSString *) title;
-(void) addCard: (AddressCard *) card;
-(void) list;
@end
#import "AddressBook.h"
@implementation AddressBook
@synthesize title, book;
-(instancetype) initWithTitle: (NSString *) theTitle
{
self = [super init];
if (self) {
title = [NSString stringWithString: theTitle];
book = [NSMutableArray array];
}
return self;
}
-(instancetype) init
{
return [self initWithTitle: @"NoTitle"];
}
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: title forKey: @"AddrBookTitle"];
[aCoder encodeObject: book forKey: @"AddrBookBook"];
// NSLog (@"AddressBook encodeWithCoder called"); called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
[aDecoder decodeObjectForKey: @"AddrBookTitle"];
[aDecoder decodeObjectForKey: @"AddrBookBook"];
// NSLog (@"AddressBook initWithCoder called"); not called
return self;
}
-(void) addCard: (AddressCard *) card
{
if ([book containsObject: card] == YES)
NSLog (@"The card already exists in %@", title);
else
[book addObject: card];
}
-(void) list
{
for (AddressCard * card in book)
[card showCard];
}
@end
#import "AddressBook.h"
#import "Foo.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Foo * myFoo1 = [[Foo alloc] init];
NSMutableData * dataArea;
NSKeyedArchiver * archiver;
AddressBook * myBook = [[AddressBook alloc] initWithTitle: @"Steve's Address Book"];
NSString * aName = @"Julia Kochan";
NSString * aEmail = @"jewls337@axlc.com";
NSString * bName = @"Tony Iannino";
NSString * bEmail = @"tony.iannino@tecfitness.com";
NSString * cName = @"Stephen Kochan";
NSString * cEmail = @"steve@steve_kochan.com";
NSString * dName = @"Jamie Baker";
NSString * dEmail = @"jbaker@hitmail.com";
NSString * filePath = @"addrbook.arch";
AddressCard * card1 = [[AddressCard alloc] initWithName: aName andEmail: aEmail];
AddressCard * card2 = [[AddressCard alloc] initWithName: bName andEmail: bEmail];
AddressCard * card3 = [[AddressCard alloc] initWithName: cName andEmail: cEmail];
AddressCard * card4 = [[AddressCard alloc] initWithName: dName andEmail: dEmail];
// Add some cards to the address book
[myBook addCard: card1];
[myBook addCard: card2];
[myBook addCard: card3];
[myBook addCard: card4];
myFoo1.strVal = @"This is the string";
myFoo1.intVal = 12345;
myFoo1.floatVal = 99.8;
// Set up a data area and connect it to an NSKeyedArchiver object
dataArea = [NSMutableData data];
archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: dataArea];
// Now we can begin to archive objects
[archiver encodeObject: myBook forKey: @"myaddrbook"];
[archiver encodeObject: myFoo1 forKey: @"myfoo1"];
[archiver finishEncoding];
// Write the archived data area to a file
if ([dataArea writeToFile: filePath atomically: YES] == NO)
NSLog (@"Archiving failed!");
NSLog (@"All operations successful!");
}
return 0;
}
解压程序代码:
#import <Foundation/Foundation.h>
@interface Foo : NSObject <NSCoding>
@property (copy, nonatomic) NSString * strVal;
@property int intVal;
@property float floatVal;
-(void) display;
@end
#import "Foo.h"
@implementation Foo
@synthesize strVal, intVal, floatVal;
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: strVal forKey: @"FoostrVal"];
[aCoder encodeInt: intVal forKey: @"FoointVal"];
[aCoder encodeFloat: floatVal forKey: @"FoofloatVal"];
// NSLog (@"Foo encodeWithCoder called"); not called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
strVal = [aDecoder decodeObjectForKey: @"FoostrVal"];
intVal = [aDecoder decodeIntForKey: @"FoointVal"];
floatVal = [aDecoder decodeFloatForKey: @"FoofloatVal"];
// NSLog (@"Foo initWithCoder called"); called
return self;
}
-(void) display
{
NSLog (@"%@\n%i\n%g", strVal, intVal, floatVal);
}
@end
#import <Foundation/Foundation.h>
@interface AddressCard : NSObject <NSCoding>
@property (nonatomic, copy) NSString * name, * email;
-(instancetype) initWithName: (NSString *) theName andEmail: (NSString *) theEmail;
-(void) showCard;
@end
#import "AddressCard.h"
@implementation AddressCard
@synthesize name, email;
-(instancetype) initWithName: (NSString *) theName andEmail: (NSString *) theEmail
{
self = [super init];
if (self) {
self.name = [NSString stringWithString: theName];
self.email = [NSString stringWithString: theEmail];
}
return self;
}
-(instancetype) init
{
return [self initWithName: @"NoName" andEmail: @"NoEmail"];
}
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: name forKey: @"AddrCardName"];
[aCoder encodeObject: email forKey: @"AddrCardEmail"];
// NSLog (@"AddressCard encodeWithCoder called"); not called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
[aDecoder decodeObjectForKey: @"AddrCardName"];
[aDecoder decodeObjectForKey: @"AddrCardEmail"];
// NSLog (@"AddressCard initWithCoder called"); called
return self;
}
-(void) showCard
{
NSLog (@"%-20s%-40s", [name UTF8String], [email UTF8String]);
}
@end
#import "AddressCard.h"
@interface AddressBook : NSObject <NSCoding>
@property (nonatomic, copy) NSString * title;
@property (nonatomic, strong) NSMutableArray * book;
-(instancetype) initWithTitle: (NSString *) title;
-(void) addCard: (AddressCard *) card;
-(void) list;
@end
#import "AddressBook.h"
@implementation AddressBook
@synthesize title, book;
-(instancetype) initWithTitle: (NSString *) theTitle
{
self = [super init];
if (self) {
title = [NSString stringWithString: theTitle];
book = [NSMutableArray array];
}
return self;
}
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: title forKey: @"AddrBookTitle"];
[aCoder encodeObject: book forKey: @"AddrBookBook"];
// NSLog (@"AddressBook encodeWithCoder called"); not called
}
-(id) initWithCoder:(NSCoder *)aDecoder
{
[aDecoder decodeObjectForKey: @"AddrBookTitle"];
[aDecoder decodeObjectForKey: @"AddrBookBook"];
// NSLog (@"AddressBook initWithCoder called"); called
return self;
}
-(void) addCard: (AddressCard *) card
{
if ([book containsObject: card] == YES)
NSLog (@"The card already exists in %@", title);
else
[book addObject: card];
}
-(void) list
{
for (AddressCard * card in book)
[card showCard];
}
@end
#import "AddressBook.h"
#import "Foo.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSData * dataArea;
NSKeyedUnarchiver * unarchiver;
Foo * myFoo1;
AddressBook * myBook;
NSString * filePath = @"addrbook.arch";
// Read in the archive and connect an
// NSkeyedUnarchiver object to it
dataArea = [NSData dataWithContentsOfFile: filePath];
if (!dataArea) {
NSLog (@"Can't read back archive file!");
return 1;
}
unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: dataArea];
// Decode the objects we previously stored in the archive
myBook = [unarchiver decodeObjectForKey: @"myaddrbook"];
myFoo1 = [unarchiver decodeObjectForKey: @"myfoo1"];
[unarchiver finishDecoding];
// Verify that the resote was successful
if (myBook != nil) {
if ([myBook.book count] == 0)
NSLog (@"Data corrupted in myBook!");
else
[myBook list];
}
else
NSLog (@"Load myBook failed!");
if (myFoo1 != nil)
[myFoo1 display];
else
NSLog (@"Load myFoo1 failed!");
}
return 0;
}
运行 以上解档程序的结果: myBook 中的数据已损坏! 这是字符串 12345 99.8 程序以退出代码结束:0
这里有两个问题:您的 AddressBook
和 AddressCard
-initWithCoder:
实现都不是
- 呼叫
self = [super init]
。这不是问题的根本原因,但肯定是不正确的 - 也不会将解码结果分配给您的任何属性。您解码
AddrBookBook
,但永远不会将其分配给self.book
;因此,myBook.book == nil
,[myBook.book count] == 0
。所有解码调用都应显示为myIvar = [aDecoder decodeObjectForKey:...]