数据存储与IO(二)
一、NSBundle资源包。
只要把文件拖到Xcode左边项目导航面板中,选择复制文件到项目中,该文件就包含进bundle中了。用[NSBundle mainBundle]获取应用程序包,常用的方法:
- URLForResource:withExtension:根据资源名和扩展名获取对应的URL。
- pathForResource:ofType:根据资源名和类型名获取对应的路径。
- resourcePath:返回该NSBundle的子目录所包含资源的完整路径。
二、NSKeyedArchiver 、NSKeyedUnarchiver归档和恢复。
归档就是用某种格式把一个或多个对象保存到指定的文件中(把对象转化为可保存、可传输的数据流),在需要的时候再从文件中恢复它们(从数据流中恢复该对象)。
NSKeyedArchiver和NSKeyedUnarchiver继承自NSCoder。
1、NSKeyedArchiver的简单用法(适用于非自定义OC对象)。
- 直接调用NSKeyedArchiver的archiveRootObject:toFile:类方法,指定一个对象为root进行归档。
- NSDictionary *dict = @{@"xiaohong" : @"小红", @"xiaoming" : @"小明"};
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- path = [path stringByAppendingPathComponent:@"dict.arch"];
- BOOL isSucc = [NSKeyedArchiver archiveRootObject:dict toFile:path];
- NSDictionary *dict = @{@"xiaohong" : @"小红", @"xiaoming" : @"小明"};
- 或者调用NSKeyedArchiver的archivedDataWithRootObject:类方法,把一个对象转换成NSData的类型并返回,再写入本地或网络。
- NSDictionary *dict = @{@"xiaohong" : @"小红", @"xiaoming" : @"小明"};
- NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dict];
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- path = [path stringByAppendingPathComponent:@"data.arch"];
- [data writeToFile:path atomically:YES];
- NSDictionary *dict = @{@"xiaohong" : @"小红", @"xiaoming" : @"小明"};
- 直接调用NSKeyedUnarchiver的unarchiveObjectWithFile:类方法进行恢复。
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- path = [path stringByAppendingPathComponent:@"dict.arch"];
- NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- 或者调用NSKeyedUnarchiver的unarchiveObjectWithData:类方法,对已经归档成NSData的单对象进行恢复。
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- path = [path stringByAppendingPathComponent:@"data1.arch"];
- NSData *data = [NSData dataWithContentsOfFile:path];
- NSDictionary *dicts = [NSKeyedUnarchiver unarchiveObjectWithData:data];
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
2、NSCoding协议的用法(适用于自定义OC对象)。
如果程序需要归档或恢复任意自定义对象,则该类必需实现NSCoding协议,并实现协议中定义的方法。
- #import <UIKit/UIKit.h>
- @interface HLPerson : NSObject <NSCoding>
- @property (copy, nonatomic) NSString *name;
- @property (assign, nonatomic) CGFloat height;
- @end
- 归档该对象时,总会调用encodeWithCoder:方法,在此方法中分别调用NSCoder的encodeXxx:forKey:方法归档对应的成员变量。
- 回复该对象时,总会调用initWithCoder:方法,在此方法中分别调用NSCoder的decodeXxxForKey:方法恢复对应的成员变量的值。
- #import "HLPerson.h"
- @implementation HLPerson
- - (void)encodeWithCoder:(NSCoder *)aCoder {
- [aCoder encodeObject:self.name forKey:@"name"];
- [aCoder encodeFloat:self.height forKey:@"height"];
- }
- - (instancetype)initWithCoder:(NSCoder *)aDecoder {
- self.name = [aDecoder decodeObjectForKey:@"name"];
- self.height = [aDecoder decodeFloatForKey:@"height"];
- return self;
- }
- @end
然后就可以像归档普通对象一样归档我们自定义的HLPerson对象了,参看1。
3、用NSData自定义归档。
前面的方法只能归档或恢复单个的OC对象,若要归档或恢复多个对象到单个文件中,则可以借助NSMutableData来创建NSKeyedArchiver或者NsKeyedUnarchiver对象。
(1)、归档步骤。
- 创建一个NSMutableData对象,并以此对象为参数调用initForWritingWithMutableData创建NSKeyedArchiver对象。
- 重复调用NSKeyedArchiver对象的encodeXxx:forKey:方法来归档所有需要归档到一个文件中的对象。
- 调用NSKeyedArchiver对象的finishEncoding方法结束归档。
- 保存该NSMutableData对象到本地或网络。
- HLPerson *person = [[HLPerson alloc] init]; // 自定义的对象需实现NSCoding协议
- person.name = @"hahh";
- person.height = ;
- NSDictionary *dict = @{@"xiaohong" : @"小红", @"xiaoming" : @"小明"};
- NSArray *array = @[person, dict];
- CGFloat age = 12.5;
- NSMutableData *data = [NSMutableData data];
- NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
- [arch encodeObject:person forKey:@"person"];
- [arch encodeObject:dict forKey:@"dict"];
- [arch encodeObject:array forKey:@"array"];
- [arch encodeFloat:age forKey:@"age"];
- [arch finishEncoding];
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- path = [path stringByAppendingPathComponent:@"data.arch"];
- BOOL isSucc = [data writeToFile:path atomically:YES];
- HLPerson *person = [[HLPerson alloc] init]; // 自定义的对象需实现NSCoding协议
(2)、恢复步骤。
- 以NSData为参数创建NSKeyedUnarchiver对象。
- 重复调用NSKeyedUnarchiver对象的decodeXxx:forKey:方法来从一个文件中恢复所有归档过的对象。
- 调用NSKeyedUnarchiver对象的finishEncoding方法结束恢复。
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- path = [path stringByAppendingPathComponent:@"data.arch"];
- NSData *data = [NSData dataWithContentsOfFile:path];
- NSKeyedUnarchiver *unarch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
- HLPerson *person = [unarch decodeObjectForKey:@"person"];
- NSDictionary *dict = [unarch decodeObjectForKey:@"dict"];
- NSArray *array = [unarch decodeObjectForKey:@"array"];
- CGFloat age = [unarch decodeFloatForKey:@"age"];
- [unarch finishDecoding];
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
延伸:归档会将整个对象转换成字节数据,包括该对象的所有成员变量,如果该成员变量指向另一个OC对象,则此OC对象也将一起被归档成字节数据。这就表明:当归档一个对象时,系统会把该对象关联的所有数据,都转换为字节数据。如果程序从这些字节数据中恢复对象,则恢复出来的对象和原来的对象相同,但在内存上的地址不同,这就实现了对象的深复制。
三、NSUserDefaults
NSUserDefaults是一个单例类,一般用来保存程序参数、用户账号、选项相关的少量数据,用它存储的对象放在沙盒的Library/Preferences目录下的文件中。
1、存储OC类型的对象:
- standardUserDefaults:获取该单例对象。
setXxx:forKey:根据key设置要存储的对象。
synchronize:保存对象到Library/Preferences目录下的文件中。
- xxxForKey:根据key获取对应的对象。
- NSDictionary *dict1 = @{@"xiaohong" : @"小红", @"xiaoming" : @"小明"};
- CGFloat height = 111.1;
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
- [defaults setObject:dict1 forKey:@"dict1"];
- [defaults setFloat:height forKey:@"height"];
- [defaults synchronize];
- NSDictionary *dict2 = [defaults objectForKey:@"dict1"];
- NSLog(@"%@ ---- %@ ---- %.2f", dict2[@"xiaohong"], dict2[@"xiaoming"], height);
- NSDictionary *dict1 = @{@"xiaohong" : @"小红", @"xiaoming" : @"小明"};
NSUserDefaults支持的数据类型有:NSNumber(NSInteger、float、double),NSString,NSDate,NSArray,NSDictionary,NSData,BOOL。存储的对象全是不可变的。
2、存储自定义类型的对象:
NSUserDefaults不支持自定义对象,可以把自定义对象转成NSData类型进行存储:
- 自定义的类需遵守NSCoding协议,且实现协议方法:encodeWithCoder:和initWithCoder:。
- 第一种方法是:调用NSKeyedArchiver的archivedDataWithRootObject:类方法,把一个对象转换成NSData的类型并返回。第二中方法是:创建一个NSMutableData对象,并以此对象为参数调用initForWritingWithMutableData创建NSKeyedArchiver对象,重复调用NSKeyedArchiver对象的decodeObjectForKey:forKey:方法来归档所有需要归档到一个文件中的对象,调用NSKeyedArchiver对象的finishEncoding方法结束归档。
- 调用NSUserDefaults的setObject:dict1 forKey:存储上一步骤得到的NSData或NSMutableData对象。(参考本篇二)
恢复对象:
- 调用NSUserDefaults的objectForKey:取出对应的NSData对象。
- 第一种方法是:调用NSKeyedUnarchiver的unarchiveObjectWithData:类方法,对已经归档成NSData的对象进行恢复。第二中方法是:以上一步得到的NSData对象为参数创建NSKeyedUnarchiver对象,重复调用NSKeyedUnarchiver对象的decodeObject:forKey:方法来从一个文件中恢复所有归档过的对象,调用NSKeyedUnarchiver对象的finishEncoding方法结束恢复。(参考本篇二)
注:对相同的key进行赋值,相当于覆盖原有的值。
四、属性列表
属性列表适合保存少量简单的数据,Xcode能以图形化的方式来编辑属性列表文件。
- writeToFile:atomically:把目标对象写入文件。
- xxxWithContentsOfFile:初始化对象。
- NSDictionary *dict1 = @{@"xiaohong" : @"小红", @"xiaoming" : @"小明"};
- NSDictionary *dict2 = @{@"xiaogong" : @"小刚", @"xiaoqiang" : @"小强"};
- NSArray *array1 = @[dict1, dict2];
- NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- path = [path stringByAppendingPathComponent:@"data.plist"];
- [array1 writeToFile:path atomically:YES];
- NSArray *array2 = [NSArray arrayWithContentsOfFile:path];
- NSLog(@"%@ ---- %@ ---- %@ ---- %@", [array2[] objectForKey:@"xiaohong"], [array2[] objectForKey:@"xiaoming"], [array2[] objectForKey:@"xiaogong"] ,[array2[] objectForKey:@"xiaoqiang"]);
- NSDictionary *dict1 = @{@"xiaohong" : @"小红", @"xiaoming" : @"小明"};
属性列表只能保存下列类型的对象:NSArray、NSMutableArray、NSDictionary、NSMutableDictionary、NSData、NSMutableData、NSString、NSMutableString、NSValue和NSNumber。
如果需要保存自定义的对象,可以使用对象归档的方式,详见二。
五、SQLite3
详见SQLite3的基本使用。
六、Core Data
七、FMDB
详见FMDB的简单使用。
数据存储与IO(二)的更多相关文章
- 数据存储与IO(一)
应用程序沙盒简介:iOS应用程序只能在系统为它分配的文件区域内读写文件,这个区域就是此应用程序的沙盒,Application目录下的GUID文件夹就是沙盒,这个文件夹是系统随机命名的.程序所有的非代码 ...
- android学习笔记45——android的数据存储和IO
android的数据存储和IO SharedPreferences与Editor简介 SharedPreferences保存的数据主要是类似于配置信息格式的数据,因此其保存的数据主要是简单的类型的ke ...
- Android系统的五种数据存储形式(二)
之前介绍了Android系统下三种数据存储形式,今天补充介绍另外两种,分别是内容提供者和网络存储.有些人可能认为内存提供者和网络存储更偏向于对数据的操作而不是数据的存储,但这两种方式确实与数据有关,所 ...
- 【Android】数据存储-java IO流文件存储
1.数据持久化:将在内存中的瞬时数据保存在存储设备中.瞬时数据:设备关机数据丢失.持久化技术提供一种机制可以让数据在瞬时状态和持久状态之间转换. 2.Android中简单的三种存储方式:文件存储.Sh ...
- Android数据存储之IO
Android开发中免不了数据本地的存储,今天我们来说一说怎样利用IO流来进行数据存储. 这里我们通过模拟一个QQ登陆界面的小demo来实际操作IO流. 功能描写叙述:点击button能够保存用户输入 ...
- Spark RDD概念学习系列之Spark的数据存储(十二)
Spark数据存储的核心是弹性分布式数据集(RDD). RDD可以被抽象地理解为一个大的数组(Array),但是这个数组是分布在集群上的. 逻辑上RDD的每个分区叫一个Partition. 在Spar ...
- IOS高级编程之二:IOS的数据存储与IO
一.应用程序沙盒 IOS应用程序职能在系统为该应用所分配的文件区域下读写文件,这个文件区域就是应用程序沙盒.所有的非代码文件如:图片.声音.映象等等都存放在此. 在mac中command+shift+ ...
- [ Android 五种数据存储方式之二 ] —— 文件存储数据
关于文件存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的. 文件可用来存放大量数据,如文本.图片.音 ...
- edgedb 内部pg 数据存储的探索 (二) 创建数据库命令说明
前面已经创建好了一个简单可以访问pg 的edgedb 环境,现在测试几个数据库操作命令在pg 的存储 创建数据库 连接环境 注意账户是按照上次创建的环境配置 edgedb -u edgedb 创建数据 ...
随机推荐
- Git undo 操作
相比传统的版本管理工具,git 的 undo 操作也不是很简单明了,本文尝试总结常用的 undo 操作. 重新提交 应该避免考虑不周全的提交,但这太难了.因此Git 专门提供了一个命令来弥补粗心的提交 ...
- 我读过的最好的epoll讲解--转自”知乎“
首先我们来定义流的概念,一个流可以是文件,socket,pipe等等可以进行I/O操作的内核对象. 不管是文件,还是套接字,还是管道,我们都可以把他们看作流. 之后我们来讨论I/O的操作,通过read ...
- Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)
在前面的随笔<Entity Framework 实体框架的形成之旅--Code First的框架设计(5)>里介绍了基于Code First模式的实体框架的经验,这种方式自动处理出来的模式 ...
- wcf和web service的区别
1.WebService:严格来说是行业标准,不是技术,使用XML扩展标记语言来表示数据(这个是夸语言和平台的关键).微软的Web服务实现称为ASP.NET Web Service.它使用Soap简单 ...
- 【vbs】vbs写ini文件
这两天在折腾给一个项目打安装包,第一次接触软件打包,用的Advanced Installer(以下简称AI),应该说如果安装过程没有特殊动作(常规动作指释放文件.写注册表.建快捷方式等)的话,倒挺傻瓜 ...
- c++错误代码1
今天敲c++,出现一个错误,这个题目错误代码如下: 并没有提示有错误而终止. 运行结果却错了: 很明显,错误的地方是变量r没有初始化. 这让我知道了,这种情况下的某些变量未经初始化而使用编译器是不会报 ...
- python signal(信号)
信号的概念 信号(signal)-- 进程之间通讯的方式,是一种软件中断.一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号. 几个常用信号: SIGINT 终止进程 中断进 ...
- 通过jQuery的比较来认识AngularJS
通过jQuery的比较来认识AngularJS 这一章主要是通过几个例子分别通过jQuery和AngularJS来达到效果.主要通过思维转换来进一步了解AngularJS框架设计背后的思想. 注意: ...
- Verilog学习笔记设计和验证篇(五)...............层次化事件队列
详细的了解层次化事件队列有助于理解Verilog的阻塞赋值和非阻塞赋值功能.所谓层次化事件队列指的是用于调度仿真时间的不同Verilog事件队列.在IEEE的5.3节中定义了层次化事件队列在逻辑上分为 ...
- 通俗易懂地讲解TCP建立连接的三次握手和释放连接的四次挥手
TCP建立连接时,为什么要进行三次挥手? 每一次TCP连接都需要三个阶段:连接建立.数据传送和连接释放.三次握手就发生在连接建立阶段. 在谢希仁著<计算机网络>第四版中讲三次握手的目的是为 ...