转载自:http://www.cnblogs.com/yjmyzz/archive/2011/03/03/1969859.html
obj-c中有一类对象:NSArray,NSDictionary,NSString,NSNumber,NSDate,NSData以及它们的可变版本(指NSMutableArray,NSMutableDictionary...这一类) ,都可以方便的将自身的数据以某种格式(比如xml格式)序列化后保存成本地文件。
示例代码:NSArrayTest.h
1 |
#import
<Foundation/Foundation.h> |
2 |
#define
FILE_NAME @"/tmp/data.txt" |
4 |
@interface NSArrayTest : NSObject { |
NSArrayTest.m
01 |
#import
"NSArrayTest.h" |
03 |
@implementation NSArrayTest |
07 |
NSArray *arr
= [NSArray arrayWithObjects:@"one",@"two",@"three",nil]; |
08 |
[arr
writeToFile:FILE_NAME atomically:YES]; |
10 |
NSArray *arr2
= [NSArray arrayWithContentsOfFile:FILE_NAME]; |
运行结果:
2011-03-03 14:20:01.501 pList[1246:a0f] (
one,
two,
three
)
如果查看/tmp/data.txt,能看到下面的内容:
1 |
<?xml version="1.0" encoding="UTF-8"?> |
即NSArray默认是以xml格式来序列化对象的.
如果你用来存放数据的类是自己定义的,并不是上面这些预置的对象,那么就要借助正式协议NSCoding来实现序列化和反序列化。
比如,我们有一个自己的类Sample.h
01 |
#import
<Foundation/Foundation.h> |
03 |
@interface Sample
: NSObject<NSCoding>
{ |
08 |
NSMutableArray *subThingies; |
11 |
@property(copy) NSString*
name; |
12 |
@property int magicNumber; |
13 |
@property float shoeSize; |
14 |
@property (retain) NSMutableArray *subThingies; |
17 |
-(id)
initWithName:(NSString *)n
magicNumber:(int)m
shoeSize:(float)
ss; |
这里我们定义几个不同类型的属性,有字符串,有整数,有浮点数,还有一个可变长的数组对象
Sample.m
03 |
@implementation Sample |
06 |
@synthesize magicNumber; |
08 |
@synthesize subThingies; |
10 |
-(id)
initWithName:(NSString *)n
magicNumber:(int)m
shoeSize:(float)ss |
12 |
if (self=[super init]) |
17 |
self.subThingies
= [NSMutableArray array]; |
25 |
[subThingies
release]; |
30 |
-(void)
encodeWithCoder:(NSCoder *)aCoder |
32 |
[aCoder
encodeObject:name forKey:@"name"]; |
33 |
[aCoder
encodeInt:magicNumber forKey:@"magicNumber"]; |
34 |
[aCoder
encodeFloat:shoeSize forKey:@"shoeSize"]; |
35 |
[aCoder
encodeObject:subThingies forKey:@"subThingies"]; |
39 |
-(id)
initWithCoder:(NSCoder *)aDecoder |
41 |
if (self=[super init]) |
43 |
self.name
= [aDecoder decodeObjectForKey:@"name"]; |
44 |
self.magicNumber
= [aDecoder decodeIntForKey:@"magicNumber"]; |
45 |
self.shoeSize
= [aDecoder decodeFloatForKey:@"shoeSize"]; |
46 |
self.subThingies
= [aDecoder decodeObjectForKey:@"subThingies"]; |
53 |
-(NSString*)
description |
55 |
NSString *description
= [NSString stringWithFormat:@"%@:%d/%.1f
%@",name,magicNumber,shoeSize,subThingies]; |
注意其中的:encodeWithCoder与initWithCoder,这是NSCoding协议中定义的二个方法,用来实现对象的编码与解码。其实现也不复杂,利用的是key-value的经典哈希结构。当然一般在编码中,对于key的名字字符串,建议用define以常量方式事先定义好,以避免开发人员字符串键入错误。
测试一下:
01 |
#import
<Foundation/Foundation.h> |
04 |
int main
(int argc, const char *
argv[]) { |
05 |
NSAutoreleasePool *
pool = [[NSAutoreleasePool alloc]
init]; |
07 |
Sample
*s1 = [[Sample alloc] initWithName:@"thing1" magicNumber:42
shoeSize:10.5]; |
08 |
[s1.subThingies
addObject:@"1"]; |
09 |
[s1.subThingies
addObject:@"2"]; |
11 |
NSData *data1
= [NSKeyedArchiver archivedDataWithRootObject:s1]; |
13 |
[data1
writeToFile:@"/tmp/data.txt" atomically:YES]; |
15 |
NSData *data2
= [NSData dataWithContentsOfFile:@"/tmp/data.txt"]; |
16 |
Sample
*s2 = [NSKeyedUnarchiver unarchiveObjectWithData:data2]; |
运行结果:
2011-03-03 14:36:48.540 pList[1322:a0f] thing1:42/10.5 (
1,
2
)
2011-03-03 14:36:48.548 pList[1322:a0f] thing1:42/10.5 (
1,
2
)
查看/tmp/data.txt,能看到以下内容:

由于经过了编码,里面的内容没有象前面的NSArray那样可读性强。