objective-C中的序列化(serialize)与反序列化(deserialize)

转载自: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"
3  
4 @interface NSArrayTest NSObject {
5 }
6  
7 -(void) Test;
8  
9 @end
NSArrayTest.m
01 #import "NSArrayTest.h"
02  
03 @implementation NSArrayTest
04  
05 -(void) Test
06 {
07     NSArray *arr = [NSArray arrayWithObjects:@"one",@"two",@"three",nil];//注:最后一个要以nil结尾
08     [arr writeToFile:FILE_NAME atomically:YES];//(序列化为xml格式后)保存文件
09      
10     NSArray *arr2 = [NSArray arrayWithContentsOfFile:FILE_NAME];//read file
11     NSLog(@"%@",arr2);
12  
13 }
14  
15 @end
运行结果:
2011-03-03 14:20:01.501 pList[1246:a0f] (
    one,
    two,
    three
)
如果查看/tmp/data.txt,能看到下面的内容:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 <plist version="1.0">
4 <array>
5     <string>one</string>
6     <string>two</string>
7     <string>three</string>
8 </array>
9 </plist>
即NSArray默认是以xml格式来序列化对象的.
如果你用来存放数据的类是自己定义的,并不是上面这些预置的对象,那么就要借助正式协议NSCoding来实现序列化和反序列化。

比如,我们有一个自己的类Sample.h
01 #import <Foundation/Foundation.h>
02  
03 @interface Sample : NSObject<NSCoding> {
04  
05     NSString* name;
06     int magicNumber;
07     float shoeSize;
08     NSMutableArray *subThingies;   
09 }
10  
11 @property(copyNSString* name;
12 @property int magicNumber;
13 @property float shoeSize;
14 @property (retain) NSMutableArray *subThingies;
15  
16  
17 -(id) initWithName:(NSString *)n magicNumber:(int)m shoeSize:(float) ss;
18  
19 @end
这里我们定义几个不同类型的属性,有字符串,有整数,有浮点数,还有一个可变长的数组对象
Sample.m
01 #import "Sample.h"
02  
03 @implementation Sample
04  
05 @synthesize name;
06 @synthesize magicNumber;
07 @synthesize shoeSize;
08 @synthesize subThingies;
09  
10 -(id) initWithName:(NSString *)n magicNumber:(int)m shoeSize:(float)ss
11 {
12     if (self=[super init])
13     {
14         self.name = n;
15         self.magicNumber = m;
16         self.shoeSize = ss;
17         self.subThingies = [NSMutableArray array];
18     }
19     return (self);
20 }
21  
22 -(void) dealloc
23 {
24     [name release];
25     [subThingies release];
26     [super dealloc];
27 }
28  
29 //将对象编码(即:序列化)
30 -(void) encodeWithCoder:(NSCoder *)aCoder
31 {
32     [aCoder encodeObject:name forKey:@"name"];
33     [aCoder encodeInt:magicNumber forKey:@"magicNumber"];
34     [aCoder encodeFloat:shoeSize forKey:@"shoeSize"];
35     [aCoder encodeObject:subThingies forKey:@"subThingies"];
36 }
37  
38 //将对象解码(反序列化)
39 -(id) initWithCoder:(NSCoder *)aDecoder
40 {
41     if (self=[super init])
42     {
43         self.name = [aDecoder decodeObjectForKey:@"name"];
44         self.magicNumber = [aDecoder decodeIntForKey:@"magicNumber"];
45         self.shoeSize = [aDecoder decodeFloatForKey:@"shoeSize"];
46         self.subThingies = [aDecoder decodeObjectForKey:@"subThingies"];
47     }
48     return (self);
49      
50 }
51  
52  
53 -(NSString*) description
54 {
55     NSString *description = [NSString stringWithFormat:@"%@:%d/%.1f %@",name,magicNumber,shoeSize,subThingies];
56     return (description);
57 }
58  
59  
60 @end
注意其中的:encodeWithCoderinitWithCoder,这是NSCoding协议中定义的二个方法,用来实现对象的编码与解码。其实现也不复杂,利用的是key-value的经典哈希结构。当然一般在编码中,对于key的名字字符串,建议用define以常量方式事先定义好,以避免开发人员字符串键入错误。
测试一下:
01 #import <Foundation/Foundation.h>
02 #import "Sample.h"
03  
04 int main (int argc, const char * argv[]) {
05     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];   
06  
07     Sample *s1 = [[Sample alloc] initWithName:@"thing1" magicNumber:42 shoeSize:10.5]; 
08     [s1.subThingies addObject:@"1"];
09     [s1.subThingies addObject:@"2"];
10     NSLog(@"%@",s1);   
11     NSData  *data1 = [NSKeyedArchiver archivedDataWithRootObject:s1];//将s1序列化后,保存到NSData中
12     [s1 release];
13     [data1 writeToFile:@"/tmp/data.txt" atomically:YES];//持久化保存成物理文件
14              
15     NSData *data2 = [NSData dataWithContentsOfFile:@"/tmp/data.txt"];//读取文件
16     Sample *s2 = [NSKeyedUnarchiver unarchiveObjectWithData:data2];//反序列化  
17     NSLog(@"%@",s2);
18       
19     [pool drain];
20     return 0;
21 }

运行结果:

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那样可读性强。

作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted on 2011-09-27 00:29  yang3wei  阅读(190)  评论(0编辑  收藏  举报