• objectiveC中的序列化(serialize)与反序列化(deserialize)


    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
    )
    如果查看/tmp/data.txt,能看到下面的内容:
    <?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>
    
    即NSArray默认是以xml格式来序列化对象的.
    如果你用来存放数据的类是自己定义的,并不是上面这些预置的对象,那么就要借助正式协议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
    
    注意其中的:encodeWithCoderinitWithCoder,这是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
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Android5.0 Gallery2上编译Gallery模块出错
    Ubuntu Linux系统下的SVN客户端工具PySVN
    ubuntu下如何安装及使用 pysvn-workbench
    系统数据库开启
    Ubuntu下使用SVN
    Ubuntu Linux 环境变量
    android 权限管理和签名 实现静默卸载
    Android系统权限及签名
    Android Security
    《Java程序猿面试笔试宝典》之字符串创建与存储的机制是什么
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1969859.html
Copyright © 2020-2023  润新知