初级数据持久化
沙盒
沙盒机制
- 每一个APP安装到手机上或者模拟器上, 都会自动生成三个文件夹 这三个文件夹叫沙盒 可以理解为这个APP的沙盒
- 每个APP的文件夹都是相对独立的 只能自己的应用去访问 不可以互相访问
- 文件夹中 存储的是 代码以外的 所有数据 例如(图片素材 声音 视频 文档等)也就是说 持久化文件(缓存文件)可以存储到 文件夹中
打开沙盒的各个文件夹路径
- (void)path{
/**
* 每一次运行的时候 都是重新安装的过程 都会随机生成一个新的沙盒路径(沙盒路径 的名字是随机的)
* 注意: 要获取的是 当前的沙盒路径
*
*/
// 打印沙盒主路径
NSString *appPath = NSHomeDirectory();
NSLog(@"%@",appPath);
// Documents文件夹
// 可以被iTunes备份 可以保存一些用户的数据及缓存文件等
// NSDocumentDirectory 要获取的文件夹路径
// NSUserDomainMask 搜索的范围
// YES 是否获取全路径
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, NO);
NSString *documentPath = [documents lastObject];
NSLog(@"%@",documentPath);
// 获取library文件夹路径
// Library 可以被iTunes备份
// Caches 主要存储喜用缓存文件
// Preferences 系统配置文件
NSArray *libraryArray = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryPath = [libraryArray lastObject];
NSLog(@"%@",libraryPath);
// 获取tmp文件夹的路径
// 主要存储临时文件
// 当手机重启时,该文件夹的文件会被删除(有可能不关机不重启也被删除)
NSString *tmp = NSTemporaryDirectory();
NSLog(@"%@",tmp);
}
简单对象的写入
- (void)writeFile{
// 把字符串 存储到沙盒当中
NSString *str = @"First Blood";
// 文件夹起名字 lol.txt
// 拼接文件存储的路径
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [documents lastObject];
NSString *filePath = [documentPath stringByAppendingPathComponent:@"/lol.text"];
//NSLog(@"%@",filePath);
// 进行简单对象的写入
// atomically 保护写入的作用
// 在写入过程中出现意外情况 也可以写入成功
[str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
// 写入一个数组
NSArray *array = @[@"ddd", @"大声道", @"king", @"whsta", @"DSA"];
// 获取写入的路径
NSString *arrayPath = [documentPath stringByAppendingPathComponent:@"/array.plist"];
// 写入文件
[array writeToFile:arrayPath atomically:YES];
// 写入字典
NSDictionary *dic = @{@"key1":@"vlaue1", @"key2":@"value2", @"key3":@"value3"};
NSString *dicPath = [documentPath stringByAppendingPathComponent:@"/dic.plist"];
[dic writeToFile:dicPath atomically:YES];
// 写入data
NSString *dataStr = @"且随疾风前行";
NSData *data = [dataStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *dataPath = [documentPath stringByAppendingPathComponent:@"/data"];
[data writeToFile:dataPath atomically:YES];
// data文件一般是 存储 图片 的
// UIImagePNGRepresentation 把图片转化成NSData类型
NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed:@"1.png"]);
// 拼接路径
NSString *imagePath = [documentPath stringByAppendingPathComponent:@"/imageData"];
[imageData writeToFile:imagePath atomically:YES];
//NSLog(@"%@",imagePath);
}
获取数据
// 读取数据
- (void)readFile{
// 读取
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [documents lastObject];// 获取写入的路径
// 获取写入的路径
NSString *arrayPath = [documentPath stringByAppendingPathComponent:@"/array.plist"];
NSArray *array = [NSArray arrayWithContentsOfFile:arrayPath];
NSLog(@"%@",array);
// 拼接路径
NSString *imagePath = [documentPath stringByAppendingPathComponent:@"/imageData"];
NSData *data = [NSData dataWithContentsOfFile:imagePath];
UIImage *image = [UIImage imageWithData:data];
}
NSFileManager
创建文件夹
// 创建文件夹
- (void)createFile{
// 获取要创建的路径
NSString *path = [kDocumentPath stringByAppendingPathComponent:@"/DownLoad"];
NSLog(@"%@",path);
// 创建文件管理器
// withIntermediateDirectories
// 是否复制之前的文件 如果写NO 就是不覆盖
// 不覆盖即创建文件夹失败
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isCreate = [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
// 打印是否创建成功
NSLog(@"%d",isCreate);
}
移动文件夹
// 移动文件夹
- (void)moveFile{
// 获取原路径
NSString *oldPath = [kDocumentPath stringByAppendingPathComponent:@"/DownLoad"];
// 获取新路径
NSString *newPath = [kCachesPath stringByAppendingPathComponent:@"/DownLoad"];
// 创建文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
// 移动
BOOL isMoved = [fileManager moveItemAtPath:oldPath toPath:newPath error:nil];
NSLog(@"%d",isMoved);
}
拷贝文件夹
// 拷贝文件夹
- (void)copyFile{
// 获取原路径
NSString *oldPath = [kCachesPath stringByAppendingPathComponent:@"/DownLoad"];
// 获取新路径
NSString *newPath = [kDocumentPath stringByAppendingPathComponent:@"/DownLoad"];
// 创建文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
// 拷贝
BOOL isCopy = [fileManager copyItemAtPath:oldPath toPath:newPath error:nil];
NSLog(@"%d",isCopy);
}
删除文件夹
// 删除文件夹
- (void)removeFile{
// 获取要删除的路径
// NSString *cachesPath = [kCachesPath stringByAppendingPathComponent:@"/DownLoad"];
NSString *documentPath = [kDocumentPath stringByAppendingPathComponent:@"/DownLoad"];
// 创建文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
// 删除
//[fileManager removeItemAtPath:CachesPath error:nil];
[fileManager removeItemAtPath:documentPath error:nil];
}
判断文件夹是否存在
// 判断文件夹是否存在
- (void)isExcutable{
// 获取文件路径
NSString *cachesPath = [kCachesPath stringByAppendingPathComponent:@"/DownLoad"];
NSFileManager *filemanager = [NSFileManager defaultManager];
BOOL isExcutable = [filemanager isExecutableFileAtPath:cachesPath];
NSLog(@"%d",isExcutable);
}
归档与反归档
解决思路:复杂对象的写入文件,自己创建出来的类(例如 Student类),写入的核心思想 把复杂对象 转化成简单对象,一般转化成NSData对象 进行写入
重写归档方法
// 重写归档方法
- (void)encodeWithCoder:(NSCoder *)aCoder{
// 按照一定格式归档
// 注意归档时候的key 要与 反归档的时候的key一致
[aCoder encodeObject:self.name forKey:@"name"];
// Integer类型
// 要选用与属性类型一致的编码方法
[aCoder encodeInteger:self.age forKey:@"age"];
// 一般统一使用对象类型
[aCoder encodeObject:self.imageData forKey:@"imageData"];
}
重写反归档方法
// 重写反归档方法
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self) {
// 按照一定的编码格式 和存储key标识 取出来被归档的对象(反归档)
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
self.imageData = [aDecoder decodeObjectForKey:@"imageData"];
}
return self;
}
归档
// 创建Student类
Student *stu = [[Student alloc] init];
stu.name = @"剑心";
stu.age = 12;
stu.imageData = UIImagePNGRepresentation([UIImage imageNamed:@"1.png"]);
// 创建一个可变的data
NSMutableData *data = [NSMutableData data];
// 创建归档对象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
// 将复杂对象通过归档对象转化成data
[archiver encodeObject:stu forKey:@"student"];
[stu release];
// 结束归档
[archiver finishEncoding];
> 实际上 通过 归档对象 把复杂对象 写入data中,并且写入的标识 就key
****** 归档与反归档 不是数据持久化 ******
只是把复杂对象按照编码格式 转化成data
真正的数据持久化 还是 写入文件
// 写入文件
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 拼接路径
NSString *path = [documentPath stringByAppendingPathComponent:@"SaveStudent"];
NSLog(@"%@",path);
[data writeToFile:path atomically:YES];
// 释放归档对象
[archiver release];
反归档
// 反归档
// 从沙盒中读取data数据
NSData *dataNew = [NSData dataWithContentsOfFile:path];
// 创建反归档对象(利用data创建)
NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:dataNew];
// 利用反归档对象 反归档初出发在对象
Student *stuNew = [unArchiver decodeObjectForKey:@"student"];
// 调用完成 返回归档
[unArchiver finishDecoding];
UIImage *image = [UIImage imageWithData:stuNew.imageData];
[unArchiver release];
// 如何把一个数组的 复杂对象 写入到文件中
// 遍历这个数组 把每一个复杂对象转化成简单对象(NSData)
// 然后再将data 保存到一个数组中
// 最后直接把这个数组写入到文件 进行持久化
}