转载自: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那样可读性强。