一、数据归档 解档
- 特点
“归档”是一种可以把任何对象,直接保存为文件的方式。(其中包括”归档”与”反归档(读档)”)
* 使用前提
必须是实现协议 ,通过”归档”的方式来存储,对象必须遵守NSCoding协议,也就意味着通过”归档”的方式能 将任何遵守了NSCoding协议的”对象”存储到文件中 (对象要是使用归档 解档 要遵守 NSCoding 协议)
- 归档、解档 :将一个对象写到文件
归档:创建一个NSKeyedArchiver实例,用于将对象归档到一个NSMutableData实例中,此时NSMutableData包含编码的数据,再使用键/码对需要的对象进行归档,最后告知完成,写入文件系统;
解档:也与归档对象步骤类似,创建一个NSData实例用于装载数据,并创建一个NSKeyedUnarchiver实例,对数据解码,然后使用先前用的键进行读取对象,最后告知程序解档完成;
归档/解档
这个方法一个对象归档成一个文件
//归档
NSArray *array = [NSArray arrayWithObjects:@"zhang",@"wangwu",@"lisi",nil];
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
BOOL success = [NSKeyedArchiver archiveRootObject:array toFile:filePath];
if(success){
NSLog(@"保存成功");
}
//解档
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.src"];
id array = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@",array);
归档
(此方法可以 多个对象归档成一个文件)
+ (BOOL)archive:(BJMBOUserModel *_Nonnull)model
{
// 获取路劲
NSString *__path4Cache = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) lastObject];
改修后缀名,以免与属性列表创建的文件重复,而加载成旧的的文件。 不用查字典了。。archive表归档
NSString *__filePath4Archive = [__path4Cache stringByAppendingPathComponent:ARCHIVE_FILE_PATH_FOR_USER_MODEL];
//判断文件是否可以操作
if (![[NSFileManager defaultManager] fileExistsAtPath:__filePath4Archive]) {
BOOL __created = [[NSFileManager defaultManager] createFileAtPath:__filePath4Archive contents:nil attributes:nil];
if (!__created) {
return false;
}
}
NSMutableData *__data = [[NSMutableData alloc] init];
NSKeyedArchiver *__archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:__data];
//使用键/值编码对希望包含在归档中的对象进行归档。
[__archiver encodeObject:model forKey:ARCHIVE_FILE_PATH_FOR_USER_MODEL];
[__archiver finishEncoding];
与属性列表一样,需要在最后写入文件,因为属性列表与归档都是一种序列化,最后仍需要写入文件。
BOOL isArchiveSuccess = [__data writeToFile:__filePath4Archive atomically:true];
return isArchiveSuccess;
}
解档
(此方法可以 解档多个对象)
+ (BJMBOUserModel *_Nullable)unarchive
{
NSString *__path4Cache = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) lastObject];
NSString *__filePath4Archive = [__path4Cache stringByAppendingPathComponent:ARCHIVE_FILE_PATH_FOR_USER_MODEL];
if ([[NSFileManager defaultManager] fileExistsAtPath:__filePath4Archive]) {
NSData *__data4Archived = [NSData dataWithContentsOfFile:__filePath4Archive];
if (__data4Archived) {
NSKeyedUnarchiver *__unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:__data4Archived];
id __obj4Unarchived = [__unarchiver decodeObjectForKey:ARCHIVE_FILE_PATH_FOR_USER_MODEL];
[__unarchiver finishDecoding]; //完成解档
if ([__obj4Unarchived isKindOfClass:[BJMBOUserModel class]]) {
BJMBOUserModel *__userModel = (BJMBOUserModel *)__obj4Unarchived;
return __userModel;
}
return nil;
}
}
return nil;
}
归档解档通用路径处理
-(NSString *)dataFile
{
//应用沙盒地址,返回的是一个数组
NSString *__path4Cache = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) lastObject];
// 拼接路径
NSString *__filePath4Archive = [__path4Cache stringByAppendingPathComponent:ARCHIVE_FILE_PATH_FOR_USER_MODEL];
}
删除文件
+ (BOOL)deleteFile
{
// 获取要删除的路径
NSString *__path4Cache = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) lastObject];
NSString *__filePath4Archive = [__path4Cache stringByAppendingPathComponent:ARCHIVE_FILE_PATH_FOR_USER_MODEL];
// 创建文件管理对象
NSFileManager *manager = [NSFileManager defaultManager];
if ([[NSFileManager defaultManager] fileExistsAtPath:__filePath4Archive]) {
// 删除
BOOL isDelete = [manager removeItemAtPath:__filePath4Archive error:nil];
NSLog(@"%d", isDelete);
[BJMBOUserManager sharedInstance].curUserModel = nil;
return YES;
}
else{
// 不存在,也返回 Yes
return YES;
}
return NO;
}
二、应用沙盒目录
Application应用程序包:包含了所有的资源文件和和可执行文件,上架前经过数字签名,上架后不可修改 [NSBundle mainBundle];
- Documents:保存应用程序本身运行时产生的文件或者数据,iCloud备份目录,例如:游戏进度、涂鸦软件的绘图
- 注意点:不要保存从网络上下载的文件,否则会无法上架!
- Library
- Caches:存放体积大又不需要备份的数据
- 保存临时文件,”后续需要使用”,例如:缓存图片,离线数据(地图数据)
- 系统不会清理 cache 目录中的文件
- 就要求程序开发时,”必须提供 cache 目录的清理解决方案”
- Preference:保存应用的所有偏好设置,iCloud会备份设置信息
- 用户偏好,使用 NSUserDefault 直接读写!
- 如果要想数据及时写入磁盘,还需要调用一个同步方法
- Caches:存放体积大又不需要备份的数据
- tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能
- 保存临时文件,”后续不需要使用”
- tmp 目录中的文件,系统会自动清理
- 重新启动手机,tmp 目录会被清空
- 系统磁盘空间不足时,系统也会自动清理
2.1 应用沙盒目录的常见获取方式
- 获取根目录
NSString*home = NSHomeDirectory();
- Documents目录 2种方式
- 利用沙盒根目录拼接”Documents”字符串
- 注意:不建议采用,因为新版本的操作系统可能会修改目录名
NSString*home = NSHomeDirectory();
NSString*documents =[home stringByAppendingPathComponent:@"Documents"];
- 利用NSSearchPathForDirectoriesInDomains函数
// NSUserDomainMask 代表从用户文件夹下找
// YES 代表展开路径中的波浪字符“~”
NSArray*array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, NO);
// 在iOS中,只有一个目录跟传入的参数匹配,所以这个集合里面只有一个元素
NSString*documents =[array objectAtIndex:0];
- tmp临时目录
NSString *tmp = NSTemporaryDirectory();
- Library/Caches 目录
- 方式一:利用沙盒根目录拼接”Caches”字符串
- 方式二:利用NSSearchPathForDirectoriesInDomains函数(将函数的第2个参数改为:NSCachesDirectory即可)
//获取Documents目录路径的方法:
NSString*documents =[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, NO) objectAtIndex:0]];
- Library/Preference 偏好设置
- 通过NSUserDefaults类存取该目录下的设置信息
- (IBAction)save:(id)sender {
// 获取偏好设置"单例"
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
// 存储数据
[ud setObject:@"123" forKey:@"name"];
[ud setBool:YES forKey:@"isOpen"];
// 立即写入
[ud synchronize];
}
- (IBAction)read:(id)sender {
// 获取偏好设置"单例"
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
//读取数据
NSString *name = [ud objectForKey:@"name"];
BOOL open = [ud boolForKey:@"isOpen"];
NSLog(@"%@", name);
}
三、文件操作
1. 创建文件夹:
//创建文件夹
-(void *)createDir{
NSString *documentsPath =[self dirDoc];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];
// 创建目录
BOOL res=[fileManager createDirectoryAtPath:testDirectory withIntermediateDirectories:YES attributes:nil error:nil];
if (res) {
NSLog(@"文件夹创建成功");
}else
NSLog(@"文件夹创建失败");
}
2. 创建文件
//创建文件
-(void *)createFile{
NSString *documentsPath =[self dirDoc];
NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];
BOOL res=[fileManager createFileAtPath:testPath contents:nil attributes:nil];
if (res) {
NSLog(@"文件创建成功: %@" ,testPath);
}else {
}
}
3.写数据到文件
//写文件
-(void)writeFile{
NSString *documentsPath =[self dirDoc];
NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];
NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];
NSString *content=@"测试写入内容!";
BOOL res=[content writeToFile:testPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
if (res) {
NSLog(@"文件写入成功");
}else
NSLog(@"文件写入失败");
}
4. 读文件数据
//读文件
-(void)readFile{
NSString *documentsPath =[self dirDoc];
NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];
NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];
// NSData *data = [NSData dataWithContentsOfFile:testPath];
// NSLog(@"文件读取成功: %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
NSString *content=[NSString stringWithContentsOfFile:testPath encoding:NSUTF8StringEncoding error:nil];
NSLog(@"文件读取成功: %@",content);
}
5. 删除文件
//删除文件 单一的指定的文件
-(void)deleteFile{
NSString *documentsPath =[self dirDoc];
NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];
BOOL res=[fileManager removeItemAtPath:testPath error:nil];
if (res) {
NSLog(@"文件删除成功");
}else
NSLog(@"文件删除失败");
NSLog(@"文件是否存在: %@",[fileManager isExecutableFileAtPath:testPath]?@"YES":@"NO");
}
清理缓存Caches,清理路径下的文件
1. 获取缓存文件的大小
-( float )readCacheSize
{
NSString *cachePath = [NSSearchPathForDirectoriesInDomains (NSCachesDirectory , NSUserDomainMask , YES) firstObject];
return [ self folderSizeAtPath :cachePath];
}
2. 由于缓存文件存在沙箱中,我们可以通过NSFileManager API来实现对缓存文件大小的计算。
// 遍历文件夹获得文件夹大小,返回多少 M
- ( float ) folderSizeAtPath:( NSString *) folderPath{
NSFileManager * manager = [NSFileManager defaultManager];
if (![manager fileExistsAtPath :folderPath]) return 0 ;
NSEnumerator *childFilesEnumerator = [[manager subpathsAtPath :folderPath] objectEnumerator];
NSString * fileName;
long long folderSize = 0 ;
while ((fileName = [childFilesEnumerator nextObject]) != nil ){
//获取文件全路径
NSString * fileAbsolutePath = [folderPath stringByAppendingPathComponent :fileName];
folderSize += [ self fileSizeAtPath :fileAbsolutePath];
}
return folderSize/( 1024.0 * 1024.0);
}
3. // 计算 单个文件的大小
- ( long long ) fileSizeAtPath:( NSString *) filePath{
NSFileManager * manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath :filePath]){
return [[manager attributesOfItemAtPath :filePath error : nil] fileSize];
}
return 0;
}
2. 清除缓存
- (void)clearFile
{
NSString * cachePath = [NSSearchPathForDirectoriesInDomains (NSCachesDirectory , NSUserDomainMask , YES ) firstObject];
NSArray * files = [[NSFileManager defaultManager ] subpathsAtPath :cachePath];
//NSLog ( @"cachpath = %@" , cachePath);
for ( NSString * p in files) {
NSError * error = nil ;
//获取文件全路径
NSString * fileAbsolutePath = [cachePath stringByAppendingPathComponent :p];
if ([[NSFileManager defaultManager ] fileExistsAtPath :fileAbsolutePath]) {
[[NSFileManager defaultManager ] removeItemAtPath :fileAbsolutePath error :&error];
}
}
//读取缓存大小
float cacheSize = [self readCacheSize] *1024;
self.cacheSize.text = [NSString stringWithFormat:@"%.2fKB",cacheSize];
}
// 删除文件 路径下的所有文件夹
-(void)clearCache:(NSString *)path{
NSFileManager *fileManager=[NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:path]) {
NSArray *childerFiles=[fileManager subpathsAtPath:path];
for (NSString *fileName in childerFiles) {
//如有需要,加入条件,过滤掉不想删除的文件
NSString *absolutePath=[path stringByAppendingPathComponent:fileName];
[fileManager removeItemAtPath:absolutePath error:nil];
}
}
// [[SDImageCache sharedImageCache] clearMemory];
}