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

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(copy) NSString* 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那样可读性强。

这里还有篇文章,直接写了个NSData分类,可以序列化所有类,非常方便

http://www.cocoachina.com/bbs/read.php?tid=35028&keyword=%D0%F2%C1%D0%BB%AF

作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2011-11-24 00:18  Kalou  阅读(254)  评论(0编辑  收藏  举报