归档

归档

       概念:在Objective-c术语中,归档是指用某种格式来保存一个对象,以便以后还原这些对象的过程。通常这个过程包括将(多个)对象写入文件中,以便以后读回该对象。

       两种归档数据的方法:属性列表和带键值的编码。

一、使用XML属性列表进行归档

1XML属性列表:MAC OS X上的应用程序使用XML属性列表(plists)束来存储诸如默认参数选择,应用程序设置和配置信息这样的数据。

注:

1>、:这些列表的归档用途是有限的,因为当为某个数据结构创建属性列表时,没有保存特定的对象类,没有存储对同一对象的多个引用,也没有保持对象的可变性。

2>属性列表归档只针对于Foundation对象

2、将数据以XML格式写出:当你的对象是NSStringNSDictionaryNSArrayNSDataNSNumber对象,你可以使用在这些类中实现的writeToFile: atomically: 方法将数据写到文件中。

3、将XML属性列表读入程序:使用dictionaryWithContentsOfFile: arrayWithContentsOfFile:方法。

注:读回数据使用dataWithContentsOfFile: 方法,要读回字符串对象,使用stringWithContentsOfFile; 方法。

4、例--

#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSAutoreleasePool.h>
int main (int argc, char *argv[])
{
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	NSDictionary *glossary =[NSDictionary dictionaryWithObjectsAndKeys:
		@"A class defined so other classes can inherit from it.", @"abstract class",
		@"To implement all the methods defined in a protocol", @"adopt",
		@"Storing an object for later use. ", @"archiving",
		nil
	];
	if ([glossary writeToFile: @"glossary" atomically: YES] == NO)
		NSLog (@"Save to file failed! ");
	[pool drain];
	return 0;
}

         希望首先将字典写入临时备份文件中,写入成功后,将把最终数据转移到名为glossary的指定文件中。这项安全措施可使得文件在执行操作的过程中崩溃时免受破坏。

glossary文件的内容如下:

<?xml version= "1.0" encoding= "UTF-8 "?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version= "1.0">
	<dict>
		<key>abstract class</key>   //属性列表
		<string>A class defined so other classes can inherit from it.</string>
		<key>adopt</key>
		<string>To implement all the methods defined in a protocol</string>
		<key>archiving</key>
		<string>Storing an object for later use. </string>
	</dict>
</plist>

注意:根据字典创建属性列表时,字典中的键必须全是NSString对象。字典中的值可以是NSStringNSArray、 NSDictionary、 NSData、 NSNumber对象

#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSAutoreleasePool.h>
int main (int argc, char *argv[])
{
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	NSDictionary *glossary;
	glossary = [NSDictionary dictionaryWithContentsOfFile: @"glossary"];
	for ( NSString *key in glossary )
	NSLog (@"%@: %@", key, [glossary objectForKey: key]);
	[pool drain];
	return 0;
}

注意:属性列表文件不必一定由程序创建,可以来自文本编辑器,或/Developer/Applications/Utilities下的Property List Editor

二、使用NSKeyedArchiver归档

1NSArchiver类:创建连续的(sequential)归档。连续的归档需要完全按照写入时的顺序读取归档中的数据。

2NSKeyedArctiver类:创建带键的归档:归档某个对象时,会为它提供一个名称,即键。

注:从归档中检索该对象时,是根据这个键来检索它的。这样,可以按照任意的顺序将对象写入归档并进行检索。

注意:iPhone SDK中没有提供NSArchiver。如果想在iPhone上使用归档功能,则必须使用NSKeyedArchiver

3、使用要求:需要导入<Foundation/NSKeyedArchiver.h>

4写入文件:archiveRootObject:toFile:方法将对象存储到磁盘上。

#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSAutoreleasePool.h>
int main (int argc, char *argv[])
{
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	NSDictionary *glossary =[NSDictionary dictionaryWithObjectsAndKeys:
		@"A class defined so other classes can inherit from it",
		@"abstract class",
		@"To implement all the methods defined in a protocol",
		@"adopt",
		@"Storing an object for later use",
		@"archiving",
		nil
 	];
	[NSKeyedArchiver archiveRootObject: glossary toFile: @"glossary.archive"];
	[pool release];
	return 0;
}

5从文件读取:通过NSKeyedUnarchiverunArchiverObjectWithFile:方法将创建的归档文件读入执行程序中

#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSAutoreleasePool.h>
int main (int argc, char *argv[]){
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	NSDictionary *glossary;
	glossary = [NSKeyedUnarchiver unarchiveObjectWithFile:@"glossary.archive"];
	for ( NSString *key in glossary )
		NSLog (@"%@: %@", key, [glossary objectForKey: key]);
	[pool drain];
	return 0;
}

三、编码方法和解码方法

1、通常自定义类对象不能直接归档,必须告知系统如何归档(或编码)你的对象,以及如何解归档(解码)它们。

2、要求:必须遵守<NSCoding>协议,在类定义中添加encodeWithCoder: 方法和initWithCoder: 方法以实现归档对象和恢复对象。

注:编码方法一般应指定如何归档想要保存的对象中的每个实例变量。

3、在带键的档案中编码和解码基本数据类型

编码方法

解码方法

encodeBool: forKey

decodeBool: forKey

encodeInt:  forKey

decodeInt:  forKey

encodeInt31: forKey

decodeInt32: forKey

encodeInt64: forKey

decodeInt64: forKey

encodeFloat: forKey

decodeFloat: forKey

encodeDouble: forKey

decodeDouble: forKey

注:对于基本的Objective-C类,可以使用encodeObject:forKey:decodeObjectforKey:编码和解码

4、例--

======== Addresscard.h接口文件======== 

#import <Foundation/Object.h>
#import<Foundation/NSString.h>
#import<Foundation/NSKeyedArchiver.h>
@interface AddressCard : NSObject <NSCopying, NSCoding> 
{
	NSString *name;
	NSString *email;
}
@property (nonatomic, copy) NSString *name, *email;
	-(void) setName: (NSString *) theName andEmail: (NSString *) theEmail;
	-(NSComparisonResult) compareNames: (id) element;
	-(void) print
	//Additional methods for NSCopying protocol
	-(AddressCard *) copyWithZone: (NSZone *) zone;
	-(void) retainName: (NSString *) theName andEmail: (NSString *) theEmail;
@end

======== 添加到AddressCard类实现文件方法========

-(void) encodeWithCoder: (NSCoder *) encoder
{
	[encoder encodeObject: name forKey: @”AddressCardName”];
	[encoder encodeObject: email forKey: @”AddressCardEmail”];
}
-(id) initWithCoder: (NSCoder *)decoder
{
	Name=[[decoder decodeObjectforKey: @”AddressCardName”]retain];
	Emame=[[decoder decodeObjectforKey: @”AddressCardEmail”]retain];
}

四、使用NSData创建自定义档案

1有时可能不希望使用archiveRootObject:ToFile:方法将对象直接写入文件,而是临时放到有NSData对象创建的临时存储空间中保存

2NSData类:可以收集一些或全部对象,并将其存储到单个档案文件中。

3NSData对象可以用来保留一块内存空间以备后来存储数据。这些数据空间的典型应用是作为一些数据的临时存储空间,如随后将被写入文件,或可能用于容纳从磁盘读取的文件内容。

4、例---

========编码=========

#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSCoder.h>
#import <Foundation/NSData.h>
#import "AddressBook.h"
#import "Foo.h"
int main (int argc, char *argv[])
{
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	Foo *myFoo1 = [[Foo alloc] init];
	Foo *myFoo2;
	NSMutableData *dataArea;
	NSKeyedArchiver *archiver;
	AddressBook *myBook;
	// Insert code from Program 19.7 to create an Address Book
	// in myBook containing four address cards
	[myFoo1 setStrVal: @"This is the string"];
	[myFoo1 setIntVal: 12345];
	[myFoo1 setFloatVal: 98.6];
	// 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  to a file
	if ( [dataArea writeToFile: @"myArchive" atomically: YES] == NO)
		NSLog (@"Archiving failed!");
	[archiver release];
	[myFoo1 release];
	[pool drain];
	return 0;
}

========解码=======

#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSCoder.h>
#import <Foundation/NSData.h>
#import "AddressBook.h"
#import "Foo.h"
int main (int argc, char *argv[])
{
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	NSData *dataArea;
	NSKeyedUnarchiver *unarchiver;
	Foo *myFoo1;
	AddressBook *myBook;
	// Read in the archive and connect an
	// NSKeyedUnarchiver object to it
	dataArea = [NSData dataWithContentsOfFile: @"myArchive"];
	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];
	[unarchiver release];
	// Verify that the restore was successful
	[myBook list];
	NSLog (@"%@\n%i\n%g", [myFoo1 strVal],[myFoo1 intVal], [myFoo1 floatVal]);
	[pool release];
	return 0;
}

五、使用归档程序复制对象

1、简介:使用Foundation的归档能力可以创建对象的深复制。

2、例--

#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSArray.h>
int main (int argc, char *argv[])
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	NSData *data;
	NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:
		[NSMutableString stringWithString: @"one"],
		[NSMutableString stringWithString: @"two"],
		[NSMutableString stringWithString: @"three"],
		nil
	];    
	NSMutableArray *dataArray2;
	NSMutableString *mStr;
	// Make a deep copy using the archiver
	data = [NSKeyedArchiver archivedDataWithRootObject: dataArray];
	dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData: data];  
	mStr = [dataArray2 objectAtIndex: 0];
	[mStr appendString: @"ONE"];
	NSLog (@"dataArray: ");
	for ( NSString *elem in dataArray )
		NSLog ("%@", elem);
	NSLog (@"\ndataArray2: ");
	for ( NSString *elem in dataArray2 )
		NSLog ("%@", elem);
	[pool drain];
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值