obj-c中有一类对象:NSArray,NSDictionary,NSString,NSNumber,NSDate,NSData以及它们的可变版本(指NSMutableArray,NSMutableDictionary...这一类) ,都可以方便的将自身的数据以某种格式(比如xml格式)序列化后保存成本地文件。
示例代码:NSArrayTest.h
#import <Foundation/Foundation.h>
#define FILE_NAME @"/tmp/data.txt"
@interface NSArrayTest : NSObject {
}
-(void) Test;
@end
NSArrayTest.m
#import "NSArrayTest.h"
@implementation NSArrayTest
-(void) Test
{
NSArray *arr = [NSArray arrayWithObjects:@"one",@"two",@"three",nil];//注:最后一个要以nil结尾
[arr writeToFile:FILE_NAME atomically:YES];//(序列化为xml格式后)保存文件
NSArray *arr2 = [NSArray arrayWithContentsOfFile:FILE_NAME];//read file
NSLog(@"%@",arr2);
}
@end
运行结果:
2011-03-03 14:20:01.501 pList[1246:a0f] (
one,
two,
three
)
one,
two,
three
)
如果查看/tmp/data.txt,能看到下面的内容:
1
2
3
4
5
6
7
8
9
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<
plist
version
=
"1.0"
>
<
array
>
<
string
>one</
string
>
<
string
>two</
string
>
<
string
>three</
string
>
</
array
>
</
plist
>
|
如果你用来存放数据的类是自己定义的,并不是上面这些预置的对象,那么就要借助
正式协议NSCoding来实现序列化和反序列化。
比如,我们有一个自己的类Sample.h
#import <Foundation/Foundation.h>
@interface Sample : NSObject<NSCoding> {
NSString* name;
int magicNumber;
float shoeSize;
NSMutableArray *subThingies;
}
@property(copy) NSString* name;
@property int magicNumber;
@property float shoeSize;
@property (retain) NSMutableArray *subThingies;
-(id) initWithName:(NSString *)n magicNumber:(int)m shoeSize:(float) ss;
@end
这里我们定义几个不同类型的属性,有字符串,有整数,有浮点数,还有一个可变长的数组对象
Sample.m
#import "Sample.h"
@implementation Sample
@synthesize name;
@synthesize magicNumber;
@synthesize shoeSize;
@synthesize subThingies;
-(id) initWithName:(NSString *)n magicNumber:(int)m shoeSize:(float)ss
{
if (self=[super init])
{
self.name = n;
self.magicNumber = m;
self.shoeSize = ss;
self.subThingies = [NSMutableArray array];
}
return (self);
}
-(void) dealloc
{
[name release];
[subThingies release];
[super dealloc];
}
//将对象编码(即:序列化)
-(void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:name forKey:@"name"];
[aCoder encodeInt:magicNumber forKey:@"magicNumber"];
[aCoder encodeFloat:shoeSize forKey:@"shoeSize"];
[aCoder encodeObject:subThingies forKey:@"subThingies"];
}
//将对象解码(反序列化)
-(id) initWithCoder:(NSCoder *)aDecoder
{
if (self=[super init])
{
self.name = [aDecoder decodeObjectForKey:@"name"];
self.magicNumber = [aDecoder decodeIntForKey:@"magicNumber"];
self.shoeSize = [aDecoder decodeFloatForKey:@"shoeSize"];
self.subThingies = [aDecoder decodeObjectForKey:@"subThingies"];
}
return (self);
}
-(NSString*) description
{
NSString *description = [NSString stringWithFormat:@"%@:%d/%.1f %@",name,magicNumber,shoeSize,subThingies];
return (description);
}
@end
注意其中的:
encodeWithCoder与
initWithCoder,这是NSCoding协议中定义的二个方法,用来实现对象的编码与解码。其实现也不复杂,利用的是key-value的经典哈希结构。当然一般在编码中,对于key的名字字符串,建议用define以常量方式事先定义好,以避免开发人员字符串键入错误。
测试一下:
#import <Foundation/Foundation.h>
#import "Sample.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Sample *s1 = [[Sample alloc] initWithName:@"thing1" magicNumber:42 shoeSize:10.5];
[s1.subThingies addObject:@"1"];
[s1.subThingies addObject:@"2"];
NSLog(@"%@",s1);
NSData *data1 = [NSKeyedArchiver archivedDataWithRootObject:s1];//将s1序列化后,保存到NSData中
[s1 release];
[data1 writeToFile:@"/tmp/data.txt" atomically:YES];//持久化保存成物理文件
NSData *data2 = [NSData dataWithContentsOfFile:@"/tmp/data.txt"];//读取文件
Sample *s2 = [NSKeyedUnarchiver unarchiveObjectWithData:data2];//反序列化
NSLog(@"%@",s2);
[pool drain];
return 0;
}
运行结果:
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
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处: http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。