7.数据归档(Archiver)

1.归档的基本概念

  1. 归档: 是指将数据写入文件存储到程序的沙盒中,当再次重新打开程序时,可以还原这些数据. 称它为数据序列化, 数据持久化. 临时数据: 存储在内存中的数据, 程序关闭, 内存释放,数据丢失
  2. 数据持久性的方式
    1) NSKeyedArchiver—-对象归档
    2) NSUserDefaults
    3) 属性列表化(NSArray, NSDictionaty保存文件)
    4) SQlite数据库, Core Data数据库
  3. 归档的形式
    1) 对Foundation库中对象进行归档
    2) 自定义对象进行归档(需要实现归档协议, NSCoding)
  4. 归档后的文件是加密的,属性列表是明文的.
  5. 归档
    1) 使用NSData实例作为归档的存储数据
    2) 添加归档的内容(设置key与value)
    3) 完成归档
    4) 将归档数据存入磁盘中
  6. 解归档
    1) 从磁盘读取文件, 生成NSData实例
    2) 根据Data实例创建和初始化解归档实例
    3) 解归档, 根据key访问value的值
  7. 苹果手机为了保证自己数据上的绝对的安全,设计了沙盒文件(其中有三个文件Documents,Library,tmp),每一个应用程序都配备了自己的沙盒文件,每一次运行,文件夹的名字就会变成一个没有任何规律的字符串
  8. 通过数组获取沙盒路径的方法有三个参数:1). 当前要前往哪一个文件夹,前往documents文件用NSDocumentDirectory,前往caches文件用NSCachesDirectory 2). 访问的文件夹的类型,指定访问是用户文件夹 3). 绝对路劲(YES),相对路劲(NO)–绝对路劲是给系统来使用的,系统可以根据当前的路劲找到文件夹.我们在操作文件的时候都是用绝对路劲,相对路劲只会把要前往的文件夹现实,其他的部分都是~,告诉程序员要去那个文件夹
  9. 沙盒(本质是一个文件夹,名字随机分配)里一共有三个文件:
    1) Documents文件是要是用来存储用户想要存储的一些信息,比如收藏的信息或者自己设置的一些内容,比如我们做的收藏功能就是往这个文件夹里写
    2) Library文件夹是方便程序开发者使用的,主要操作它里面的两个文件夹,caches和Preferences. caches:用来保存缓存文件,SDWebImage会把图片加载到缓存文件中,所以清除缓存功能就是把这个文件夹删除.Preferences一般用来保存程序员设置的信息,比如NSUserDefaults就会把数据保存到这个文件夹中
    3) tmp文件一般存放临时内容,之前版本还有一个.app文件
    这里写图片描述

2.第一种归档方式

main.m文件

**归档对象**
NSString *homepath = NSHomeDirectory();
NSString *path = [homepath stringByAppendingPathComponent:@"archiver2.plist"];
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
NSArray *array = @[@"zhangsam",@"liuyang"];
[archiver encodeObject:array forKey:@"name"];
[archiver encodeInt:100 forKey:@"number"];
[archiver finishEncoding];
BOOL success = [data writeToFile:path atomically:YES];
if (success) {
NSLog(@"success");
}
  ***解归档***
NSString *homepath = NSHomeDirectory();
NSString *path = [homepath stringByAppendingPathComponent:@"archiver2.plist"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
int number = [unArchiver decodeIntForKey:@"number"];
NSArray *array = [unArchiver decodeObjectForKey:@"name"];
NSLog(@"\n  %d  %@",number,array);

3.把简单对象写入到本地,简单对象指的是NSString,NSArray,NSDictionary,NSData

//先通过数组获取沙盒路劲,然后从数组里获取沙盒路径
NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
NSString *sandBoxPath = sandBox[0];
//要给写入的文件拼接一个路径,拼接方式有两种,一般用后面路径专有方法
//NSString *documentPath = [sandBoxPath stringByAppendingString:@"/古玉.txt"];
NSString *documentPath = [sandBoxPath stringByAppendingPathComponent:@"古玉.txt"];
NSString *str = @"隔壁老顾爱耍贱";
//把字符串写入到本地,如果路劲下有对应文件,则会把原来的文件覆盖掉,没有则新建一个文件
[str writeToFile:documentPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
//把沙盒文件再读取出来(解归档)
NSString *tempStr = [NSString stringWithContentsOfFile:documentPath encoding:NSUTF8StringEncoding error:nil];
//把数组写入到本地
NSArray *arr = @[@"1",@"2",@"3"];
//通过数组获取沙盒路径
NSArray *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *str = [documentPath[0] stringByAppendingPathComponent:@"xiyi.plist"];
[arr writeToFile:str atomically:YES];
//把数组再读出来
NSArray *array = [NSArray arrayWithContentsOfFile:str];

4.把复杂对象(在Foundation框架内不存在的数据类)写入到本地,自定义归档

1) 自定义的对象要支持归档, 需要实现NSCoding协议
2) NSCoding协议有两个方法, encodeWithCoder 方法对对象的属性数据做编码处理. initWithCoder 解码归档数据来初始化对象
3) 实现NSCoding协议后,就能通过NSKeyArchiver归档.
4.)复杂对象无法通过writeToFile:方法进行数据持久化, 能通过将复杂对象转换为NSData, 然后通过writeToFile:进行数据持久化
Student.m和Student.h文件

#import <Foundation/Foundation.h>
#pragma mark 实现归档和反归档就得签订NSCoding协议
@interface Student : NSObject<NSCoding>
@property(nonatomic,copy)NSString *name;
@property(nonatomic,copy)NSString *sex;
@property(nonatomic,assign)NSInteger age;
@property(nonatomic,copy)NSString *hobby;
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age hobby:(NSString *)hobby;
+ (instancetype)studentWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age hobby:(NSString *)hobby;
@end
#import "Student.h"
@implementation Student

#pragma mark 需要实现两个必须实现的协议方法,归档和反归档
//对属性编码,归档的时候会调用
- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInteger:_age forKey:@"age"];
    [aCoder encodeObject:_hobby forKey:@"hobby"];
    [aCoder encodeObject:_sex forKey:@"sex"];
    //使用encode方法要和数据类型相互匹配
}
//对属性解码,解归档的时候调用
- (id)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    if (self) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.hobby = [aDecoder decodeObjectForKey:@"hobby"];
        _age = [aDecoder decodeIntegerForKey:@"age"];
        self.sex = [aDecoder decodeObjectForKey:@"sex"];
    }
    return self;
}
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age hobby:(NSString *)hobby
{
    self = [super init];
    if (self) {
        self.name = name;
        self.sex = sex;
        _age = age;
        self.hobby = hobby;
    }
    return self;
}
+ (instancetype)studentWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age hobby:(NSString *)hobby
{
    Student *student = [[Student alloc] initWithName:name sex:sex age:age hobby:hobby];
    return student;
}
- (NSString *)description
{
    return [NSString stringWithFormat:@"name = %@, sex = %@, hobby = %@, age = %ld", _name,_sex,_hobby,_age];
}
- (void)dealloc
{
    [_name release];
    [_hobby release];
    [_sex release];
    [super dealloc];
}
@end

在ViewController.m文件里归档/解档操作

//复杂对象写入到本地,主要是指我们自己创建的对象写入到本地,也叫归档和反归档操作
Student *stu = [Student studentWithName:@"张三" sex:@"男" age:22 hobby:@"耍贱"];
NSArray *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//拼接路径,扩展名可以是任意的
NSString *path = [documentPath[0] stringByAppendingPathComponent:@"student.plist"];
//对对象进行归档操作,两个参数:1.归档的对象 2.路径
[NSKeyedArchiver archiveRootObject:stu toFile:path];
//反归档
Student *strdent = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSLog(@"%@",strdent);
//复杂对象放到数组里然后写入到本地
Student *stu1 = [Student studentWithName:@"张三1" sex:@"男" age:22 hobby:@"耍贱1"];
Student *stu2 = [Student studentWithName:@"张三2" sex:@"男" age:22 hobby:@"耍贱2"];
Student *stu3 = [Student studentWithName:@"张三3" sex:@"男" age:22 hobby:@"耍贱3"];
NSArray *arr = @[stu1,stu2,stu3];
NSArray *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *stuPath = [documentPath[0] stringByAppendingPathComponent:@"student.plist"];
[NSKeyedArchiver archiveRootObject:arr toFile:stuPath];
NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithFile:stuPath];
for (Student *stu in array) {
    NSLog(@"%@",stu);
}

5.归档小结和NSFileManager

#pragma mark 总结:数据持久化的步骤
// 1.指定前往哪一个文件夹 2.用字符串接受路径 3.拼接文件路径 4.写入本地或者归档操作
// 注:如果是复杂对象归档,要签订NSCoding协议且实现两个协议方法,方在数组的复杂对象也要签协议
//NSUserDefaults一般存放的是小的数据(保存在Library/Preferences文件下),比如字符串,用法和字典类似
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"123456" forKey:@"password"];
//在从本地取值的方法和字典类似
NSLog(@"%@",[defaults objectForKey:@"password"]);
//创建一个文件管理者,通过文件管理者对文件夹进行操作
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *documentPaht = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//给要创建的文件夹拼接一个路径,文件夹名不需要任何的扩展名
NSString *filePath = [documentPaht[0] stringByAppendingPathComponent:@"guyu"];
//通过manager进行文件夹的创建
[manager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
//通过manager进行文件夹的删除
[manager removeItemAtPath:filePath error:nil];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值