数据持久化

一、数据持久化概述

数据持久化就是数据的永久存储。其本质是将数据保存为文件,存到程序的沙盒中。

1、数据持久化的方式

1.1 writeToFile:简单对象写入文件

1.2 NSUserDefaults:应用程序偏好设置

1.3 Sqlite:轻量级关系型数据库,不能直接存储对象(NSData除外),需要用到一些SQL语句,先将复杂对象归档(对象->NSData)

1.4 CoreData:对象型数据库,实质是将数据库的内部存储细节封装

1.5 Plist文件

2、应用程序沙盒

每一应用程序都有自己的应用沙盒,沙盒的本质就是一个文件夹,名字是随机分配的。

与其他应用程序沙盒隔离,应用程序本身只能访问自己沙盒的数据。(iOS8+对沙盒之间的访问部分开放)

2.1应用程序包(.app)

包含了应用程序中所用到的所有资源文件和可执行文件(Base on Unix)。iOS8时,app不存储在沙盒中,有单独的文件夹存储所有程序的app包。

2.2 HomeDirectory

Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录

tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录

Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据

Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录

2.3 获取沙盒路径

沙盒根目录:NSHomeDirectory();

沙盒临时目录:NSTemporaryDirectory();

Library/Preferences:NSUserDefaults

//1.获取沙盒中Documents文件夹的路径

//第一种方式:

NSString*documentPath =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).lastObject;//NO, path = @"~/"(相对路径); YES 绝对路径

NSLog(@"%@", documentPath);

//第二种方式: (不建议采用,因为新版本的操作系统可能会修改目录名)

NSString*homePath =NSHomeDirectory();

NSString*documentPath2 = [homePathstringByAppendingPathComponent:@"library/caches"];

NSLog(@"%@", documentPath2);

//2.获取应用程序包路径(.app)

NSLog(@"%@", [NSBundlemainBundle].resourcePath);

二、简单对象持久化

1、简单对象

NSString\NSArray\NSDictionary\NSData

使用writeToFile:方法,将数据存储为.plist文件

atomically参数为是否写入缓存

//字符串

NSString*string =@"I?U";

//数组

NSArray*array =@[@"张三",@"李四",@"王五"];

//字典

NSDictionary*dictionary =@{@"name":@"张三",@"age":@"20",@"sex":@"男"};

//NSData

UIImage*image = [UIImageimageNamed:@"1.jpg"];

NSData*data =http://my.oschina.net/zooyf/blog/UIImageJPEGRepresentation(image,1);

//1.拼接存储路径

NSString*strPath = [documentPathstringByAppendingPathComponent:@"string.txt"];

NSString*arrayPath = [documentPathstringByAppendingPathComponent:@"array.txt"];

NSString*dicPath   = [documentPathstringByAppendingPathComponent:@"dict.txt"];

NSString*dataPath  = [documentPathstringByAppendingPathComponent:@"data.txt"];

//2.写入文件

[stringwriteToFile:strPathatomically:YESencoding:NSUTF8StringEncodingerror:nil];

[arraywriteToFile:arrayPathatomically:YES];

[dictionarywriteToFile:dicPathatomically:YES];

[datawriteToFile:dataPathatomically:YES];

//3.读取文件内容

NSString*fileString = [NSStringstringWithContentsOfFile:strPathencoding:NSUTF8StringEncodingerror:nil];

NSArray*fileArray = [NSArrayarrayWithContentsOfFile:arrayPath];

NSDictionary*fileDict = [NSDictionarydictionaryWithContentsOfFile:dicPath];

NSData*fileData = http://my.oschina.net/zooyf/blog/[NSDatadataWithContentsOfFile:dataPath];

NSLog(@"%@", fileString);

NSLog(@"%@", fileArray);

NSLog(@"%@", fileDict);

NSLog(@"%@", fileData);

2、文件管理类:NSFileManager

2.1、功能

NSFileManager使用defaultManager创建单例对象。可以创建文件夹,可以删除、移动、创建文件,判断文件是否存在。

2.2、使用

//缓存文件夹所在路径

NSString*cachesPath =NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES).lastObject;

NSLog(@"%@", cachesPath);

//在cachesPath路径下创建一个文件夹

NSString*directoryPath = [cachesPathstringByAppendingPathComponent:@"path"];

NSFileManager*fileManager = [NSFileManagerdefaultManager];//创建文件管理类单例对象

//根据路径创建文件夹

NSDictionary*fileDate =@{@"createTime":@"2015-9-9"};

[fileManagercreateDirectoryAtPath:directoryPathwithIntermediateDirectories:YESattributes:fileDateerror:nil];

//根据路径创建文件(只能写入NSData类型的数据)

[fileManagercreateFileAtPath:directoryPathcontents:dataattributes:fileDate];

//删除文件

[fileManagerremoveItemAtPath:dicPatherror:nil];//删除~/documents/dict.txt

3、NSUserDefaults

NSUserDefaults*defaults = [NSUserDefaultsstandardUserDefaults];//单例

[defaultssetValue:@"yfyfyfyfyfyfyfy"forKey:@"username"];

[defaultssetValue:@"123"forKey:@"password"];

//注意:UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用synchornize方法强制写入到文件中

[defaultssynchronize];

//读取

NSString*name = [defaultsvalueForKey:@"username"];

NSString*pwd = [defaultsvalueForKey:@"password"];

二、复杂对象持久化(NSKeyedArchiver)

1、复杂对象

复杂对象是在Foundation框架内不存在的数据类,无法通过writeToFile写入到文件内,且至少包含一个实例对象。

由于复杂对象无法通过writeToFile:方法写入文件,只能将复杂对象转化为NSData对象,再进行数据持久化。

2、NSCoding协议

@protocolNSCoding

- (void)encodeWithCoder:(NSCoder*)aCoder;

- (id)initWithCoder:(NSCoder*)aDecoder;// NS_DESIGNATED_INITIALIZER

@end

3、复杂对象写入文件

Person.h

//复杂对象归档一:遵守NSCoding协议

@interfacePerson :NSObject

@property(nonatomic,assign)NSIntegerage;

@property(nonatomic,retain)NSString*name;

@property(nonatomic,retain)NSString*gender;

@end

Person.m

#import"Person.h"

@implementationPerson//实现NSCoding协议

#pragma mark --进行编码--

- (void)encodeWithCoder:(NSCoder*)coder

{

//    [super encodeWithCode:coder];如果父类也遵守了NSCoding协议,确保继承的实例变量也能被编码,即也能被归档

[coderencodeObject:self.nameforKey:@"name"];

[coderencodeInteger:self.ageforKey:@"age"];

[coderencodeObject:self.genderforKey:@"gender"];

}

#pragma mark --进行解码--

- (id)initWithCoder:(NSCoder*)aDecoder

{

//    self = [super initWithCoder:aDecoder];确保继承的实例变量也能被解码,即也能被恢复

self= [superinit];

if(self) {

self.name= [aDecoderdecodeObjectForKey:@"name"];

self.gender= [aDecoderdecodeObjectForKey:@"gender"];

self.age= [aDecoderdecodeIntegerForKey:@"age"];

}

returnself;

}

@end

ViewController.m

类方法进行编码\解码(只能归档一个对象):

NSString*objPath = [cachesPathstringByAppendingPathComponent:@"person.txt"];

[NSKeyedArchiverarchiveRootObject:persontoFile:objPath];

Person*p2 = [NSKeyedUnarchiverunarchiveObjectWithFile:objPath];

实例方法(可以归档多个对象):

#pragma mark --对复杂对象进行持久化(归档\编码) --

//过程:(复杂对象->归档->NSData->writeToFile:)

Person*person = [[Personalloc]init];

person.name=@"yf";

person.age=20;

person.gender=@"man";

NSMutableData*mtData = http://my.oschina.net/zooyf/blog/[NSMutableDatadata];

//创建归档器

NSKeyedArchiver*archiver = [[NSKeyedArchiveralloc]initForWritingWithMutableData:mtData];

//进行归档

[archiverencodeObject:personforKey:@"person"];

//***结束归档

[archiverfinishEncoding];

//将归档之后的mtData写入文件

NSString*personPath = [cachesPathstringByAppendingPathComponent:@"person.txt"];

[mtDatawriteToFile:personPathatomically:YES];

NSLog(@"%@", personPath);

NSLog(@"%@", mtData);

#pragma mark --从文件中读取复杂对象(反归档\恢复\解码) --//过程:(读取文件(NSData)->反归档->复杂对象)

//读取

NSData*readData = http://my.oschina.net/zooyf/blog/[NSDatadataWithContentsOfFile:personPath];

//创建反归档工具

NSKeyedUnarchiver*unArchiver = [[NSKeyedUnarchiveralloc]initForReadingWithData:readData];

//使用反归档工具对readData进行反归档

Person*readPerson = [unArchiverdecodeObjectForKey:@"person"];

4、使用NSKeyedArchive进行深复制

比如对一个Person对象进行深复制

// 临时存储person1的数据

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person1];

// 解析data,生成一个新的Person对象

Student *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];

// 分别打印内存地址

NSLog(@"person1:0x%x", person1); // person1:0x7177a60

NSLog(@"person2:0x%x", person2); // person2:0x7177cf0



在IOS应用中数据持久化是客户端重要的东西。一般除了本地持久化就是与服务器交互数据从网上获取了,但是如果没有网络的情况下。本地持久化是必须的。一般持久化有4种方法。现在一一介绍,对于网络的就以后介绍。

第一种:实用属性列表,第二种:对象归档,第三种:使用Iphone的嵌入式数据库(SQLite3)

给予Iphone应用程序沙盒原理,我们保持的数据都是保存在相对应的应用程序的Document文件夹。既然我们把数据放在每一个应用的Document文件夹中,呢我我们怎么得到相应的路径呢,其实也不是很难。下面是检索文档目录路径的代码:

NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserdomainMask, YES);

NSString*documentDirectory = [paths objectAtIndex:0];

常量NSDocumentDirectory表面我们正在查找的Document目录路径,常量NSUserDomainmask表明我们希望将搜索限制于我们应用程序的沙盒中。这样我们就可以得到该数组的第一值,也仅此一值,因为每一个应用程序只有一个Document文件夹。我们得到了Document的路径,然后和文件名相连接不就是一个完整的路径了吗,这用到了stringByAppendingPathComponent方法:

NSString*filepath = [documentDirectorystringbyAppendingPathComponent:@"filename.xxx"];其中filename.xxx为要命名的文件。

在每一个应用程序中还对应一个temp文件夹,我们怎么获取这个文件夹的路径呢,也比较简单:

NSString*tempPath = NSTemporaryDirectory();

NSString*filePath = [tempPathstringByAppendingPathComponent:@"filename.xxx"];

NSUserDefaults类的使用和NSKeyedArchiver有很多类似之处,但是查看NSUserDefaults的定义可以看出,NSUserDefaults直接继承自NSObject而NSKeyedArchiver 继承自NSCoder。这意味着NSKeyedArchiver实际上是个归档持久化的类,也就可以使用NSCoder类的[encodeObject: (id)objv forKey:(NSString *)key]方法来对数据进行持久化存储

除了上面的三种方法来保存持久化 数据以外,我们还可以用写文件到磁盘的方式来保存持久化数据

嵌入式数据库持久化数据就是把数据保存在iphone的嵌入式数据库系统SQLite3中,本质上来说,数据库持久化操作是基于文件持久化基础之上的。 要使用嵌入式数据库SQLite3,首先需要加载其动态库libsqlite3.dylib,这个文件位于/Xcode3.1.4/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/usr/lib目录下

Core Data是一种 稳定,功能全面的持久化工具,和之前的一些持久化 工具相比,他不需要对实体进行归档,也就是序列化,而是在数据 模型编辑器中创建一些实体

在代码中,你不再使用存取方法和修改方法,而是使用键值对编码来设置属性或者减缩他们的值

那么这些托管对象的活动区域在哪 ?  他们位于所谓的持久库中,默认情况下,Core Data应用程序将持久库实现为存储在应用程序文档目录的sqlite数据库。

虽然数据是通过sqlite存储的,但框架中的类将完成加载和保存数据的相关工作。不许要编写任何sql语句。

其实在Iphone上存储数据是在iPhone系统中存储数据的,这里可以包括应用程序和互联网的一些数据信息。我们可以解析和读取这些数据。首先我们先了解下数据持久化的几种方式:首先是属性列表。nsuserdefaults位于属性列表的最顶层,我们可以在里面添加一些UI的小单元

还有就是iPhone的应用程序沙盒技术,以及对象的归档,以及第三方的SQLlite,还有就是coredata。

首先让我们说说这个属性列表:它是存储相对较小数据量的简洁方式,并且耗费非常低的工作量。但是这个属性列表也是有限制的像刚才我说的存储数据量小的数据,还有就是一些自定义的对象是不能存储的,只能是支持序列化的对象,想字典,数据,字符串,对了 还是不能添加UI界面的东西。他们可以以两种不同的方式存储一个是XML,这个XML是一种可读性非常强的格式,另一个是内部专门有的2进制的格式,这种方式速度更快写,数据量更小些。正如我们所说的NSuerdefaults位于属性列表的顶层,因此我们可以轻松的读取并且存储数据。

下面我们说说有几种情况来说明有些数据是不能存储的:比如你有大量的几百兆的数据这样是不行的,还有是一堆的图像,你将不会选择这个方式,因为你任何时候加载一个属性列表的时候他们是完全在家在内存当中的,知道一个完整的图片被创建,因此这种方式是不适用随机访问的。假如有两个线程一个是写入一个是读取这是不能同步的,同步会出现一些问题的,这是为什么呢,因为属性列表没有类似有原子性的东西。我们会有两种方式把他们写在硬盘内writetofile:@"文件路径"atomically:yes。这个原子性是什么意思呢,在这里可以这样的理解,它可以让系统写入文件一次首先是把它写入到一个临时的文件后然后在将其转移到可你以放置任何文件的没有风险的地方这里将保存着先前的文件以及任何改动的地方,因此如果操作 系统崩溃或者电池电量的耗尽的时候你也不会丢失任何的数据的。你可以从你先前的或者新的数据里获取数据而非受破坏的中间的状态。当你在写一个属性列表的时候如果你看XML和2进制。自定义和一些UI的视图不支持这些东西取决与可不可以序列化对象,当然不可以序列化,即使你序列化这些不能序列化的东西它会返回空值的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • 一、数据持久化概述 数据持久化就是数据的永久存储。其本质是将数据保存为文件,存到程序的沙盒中。 1、数据持久化的方...
    lilinjianshu阅读 595评论 0 1
  • 1、 沙盒概念基本介绍 iOS 应用程序只能在该 app 的文件系统中读取。这个默认的 app 文件系统就是我们说...
    Laughingg阅读 2,637评论 2 10
  • 1.简介 数据持久存储是一种非易失性存储,在重启动计算机或设备后也不会丢失数据。持久化技术主要用于MVC模型中的m...
    公子无礼阅读 1,671评论 0 4
  • 一、文件 应用程序包 : 这里面存放的是应用程序的源文件,包括资源文件和可执行文件。NSString *path ...
    今天又要上班吗阅读 596评论 0 2
  • 在程序开发中,数据层永远是程序的核心结构之一。我们将现实事物进行抽象,使之变成一个个数据。对这些数据的加工处理是代...
    帅不过oneS阅读 589评论 0 1