NSFileManager(沙盒文件管理)数据持久化 <序列化与反序列化>
iOS应用程序只能在为该改程序创建的文件中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文本文件等。 默认情况下,每个沙盒含有3个文件夹:Documents, Library 和 tmp,因为应用的沙盒机制,应用只能在几个目录下读写文件
1.Documents:
//保存应⽤运行时生成的需要持久化的数据,并将通过iCloud自动备份。例如,游戏应用可将游戏存档保存在该目录,iTunes备份和恢复的时候会包括此目录
2.Library:
//Library/Caches:保存应用运行时⽣成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据。比如杂志、新闻、地图应用使用的数据库缓存文件和可下载内容应该保存到这个文件夹。
//Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置) 应⽤会在该⺫录中查找应⽤的设置信息。iTunes同步设备时会备份该目录
3.tmp:
//保存应⽤运行时所需的临时数据,使⽤完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时 不会备份该目录
简单文件的写入(OC简单数据类型直接writeToFile:写入即可):
1 /*
2 路径:
3 /Users/scjy/Library/Developer/CoreSimulator/Devices/E43301D4-B5C5-4940-8A8E-305EE9605C1C/data/Containers/Data/Application/04A8FA3D-D4CD-4C30-BA87-3A3429F9135B/Documents
4 总结:新建重名时,文件夹(Directory)不被覆盖,而文件(File)会被覆盖
5 */
6
7 #import "ViewController.h"
8
9 @interface ViewController ()
10 {
11 NSString *path;
12 }
13 @property(nonatomic,assign)NSFileManager *fileMgr;
14 @end
15
16 @implementation ViewController
17
18 - (void)viewDidLoad {
19 [super viewDidLoad];
20 // NSString *homeDirectory = NSHomeDirectory();//获取根目录,APP在手机中的目录
21 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask/*当前域中寻找路径*/, YES);
22 path = [paths firstObject];//NSString *p = [paths objectAtIndex:0];//获取沙盒中的document目录
23 NSLog(@"%@",path);
24 // // 获取Cache目录
25 // NSArray *cachePaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
26 // NSString *cachePath = [cachePaths firstObject];
27 // //获取Library目录
28 // NSArray *libraryPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
29 // NSString *libraryPath = [libraryPaths firstObject];
30 // //获取temp目录
31 // NSString *tmpDir = NSTemporaryDirectory();
32 //将字符串写入刘冠.txt,如果没有此文件,系统会先创建,再写入,如果已经存在,则覆盖原有的文件
33 // NSString *string = @"刘冠";
34 // NSString *textPath = [path stringByAppendingPathComponent:@"刘冠.txt"];//@"刘冠.plist"//属性列表文件,用于存放列表数据(比如字典)
35 // [string writeToFile:textPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
36 //将图片写入沙盒,首先需要将图片转换成data
37 UIImage *image = [UIImage imageNamed:@"128"];
38 NSData *data = UIImageJPEGRepresentation(image, 1);//CG浮动压缩质量:1
39 [data writeToFile:[path stringByAppendingString:@"/1.jpg"] atomically:YES];//注意这里的atomically(原子性:是否使用辅助文件,YES:先写入辅助文件,然后辅助文件再重新命名为目标文件,NO:直接写入目标文件)如果使用stringByAppendingString拼接路径,则需要在文件前加/
40 //文件操作
41 self.fileMgr = [NSFileManager defaultManager];//创建文件管理器(利用文件管理器,通过相应方法对文件操作)
42 // [self.fileMgr removeItemAtPath:[path stringByAppendingString:@"/1.jpg"] error:nil];
43 //获取某路径下所有的文件和文件夹(目录)
44 NSArray *docs = [self.fileMgr contentsOfDirectoryAtPath:path error:nil];
45 NSLog(@"目录%@",docs);
46 [self.fileMgr createDirectoryAtPath:[path stringByAppendingString:@"/刘冠"]/*需要创建文件夹的文件夹和路径*/ attributes:nil];//创建文件夹,如果该文件夹已存在,则不会创建新的文件夹(已弃用)
47 [self.fileMgr createDirectoryAtPath:[path stringByAppendingPathComponent:@"哈哈"] withIntermediateDirectories:NO attributes:nil error:nil];//创建文件夹,如果该文件夹已存在,则不会创建新的文件夹“Intermediate:中间物”
48 // BOOL flag = [self.fileMgr fileExistsAtPath:path];//检查文件/文件夹是否存在“Exists:存在”用于移除等操作的判断
49 // BOOL isD;
50 // BOOL flag3 = [self.fileMgr fileExistsAtPath:path isDirectory:&isD];//判断文件/文件夹是否存在,且该路径是否是文件夹
51 }
52 - (IBAction)remove:(id)sender {
53 //移除操作(删除)
54 [self.fileMgr removeItemAtPath:[path stringByAppendingString:@"/1.jpg"] error:nil];
55 [self.fileMgr removeItemAtPath:[path stringByAppendingString:@"/刘冠"] error:nil];
56 [self.fileMgr removeItemAtPath:[path stringByAppendingString:@"/哈哈"] error:nil];
57 // stringByAppendingString:@"/1.jpg" = stringByAppendingPathComponent:@"1.jpg"
58 }
59 - (IBAction)Copy:(id)sender {
60 //copy操作
61 if([self.fileMgr fileExistsAtPath:[path stringByAppendingString:@"/刘冠"]])//判断"刘冠"文件是否存在
62 {
63 [self.fileMgr copyItemAtPath:[path stringByAppendingString:@"/刘冠/1.jpg"] toPath:[path stringByAppendingString:@"/哈哈/4.jpg"] error:nil];//,注意:1、(源文件)必须存在,(目标文件) 必须不存在,文件名字必须要写出来,如果(目标文件) 已经存在,则复制失败 (因为不会替换已有的文件或文件夹)2、(源文件)以及(目标文件),这两个参数必须是完整的文件路径(不考虑后缀名),不能只写到文件夹
64
65
66 //[self.fileMgr moveItemAtPath:[path stringByAppendingString:@"/刘冠/1.jpg"] toPath:[path stringByAppendingString:@"/哈哈/2.jpg"] error:nil];/*/移动,注意事项与copy一致
67 }
68 }
复杂文件的写入(自定义类的对象类型,需要归档、解档):此时该类需要遵循<NSCoding>协议,,其实NSObject已经继承过了
实现两个方法:
当用户对该类对象进行归档时,会调用此方法,该方法主要作用是对属性的封装- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"name"];//归档(编码)
[aCoder encodeObject:self.age forKey:@"age"];
}
当用户解档时,会调用此方法,并且取出属性的值- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if(self)
{
self.name = [aDecoder decodeObjectForKey:@"name"];//解档(解码)
self.age = [aDecoder decodeObjectForKey:@"age"];
}
return self;
}
实现代码:
1 Student *student = [[Student alloc]init];
2 student.name = @"刘冠";
3 student.age = @22;
4 NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"归档.plist"];//属性列表
5 NSLog(@"%@",path);
6 /*归档*/
7 //准备将对象student写入到文件中,通过归档技术(操作步骤:首先新建一个data,将archiver与data关联(此刻data无数据),通过archiver归档对象(归档入data中),最后将data写入文件)
8 NSMutableData *data = [[NSMutableData alloc]init];//归档中间媒介,需要先把数据归档入data
9 NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];//关联archiver与data(将data设为归档目的地)
10 [archiver encodeObject:student forKey:@"Student"];//归档
11 [archiver finishEncoding];
12 [data writeToFile:path atomically:YES];//数据在data中
13 //归档之后的数据我们是意想不到的
14
15 /*解档*/ /*应该先从路径获取data数据,然后在解档*/
16 NSMutableData *data1 = [[NSMutableData alloc]initWithContentsOfFile:path];
17 NSKeyedUnarchiver *uarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data1];//读到data1
Student *p = [uarchiver decodeObjectForKey:@"Student"];
18 [uarchiver finishDecoding];//这个也要写,结束解档 19 NSLog(@"解档数据%@,%@",p.name,p.age);
另一种较为方便的归档与解档(数据持久化)
//同时也要遵循<NSCoding>协议, 实现上面的两个方法 (这里只是不再通过data作为中间存储介质,而直接通过系统方法取实现归档与解档)
NSString *home = NSHomeDirectory();
NSString *path = [home stringByAppendingPathComponent:@"atany.archiver"];
//归档
[NSKeyedArchiver archiveRootObject:@"归档" toFile:path];
//解档
NSString *string = [NSKeyedUnarchiver unarchiveObjectWithFile:path ];
NSLog(@"%@",string);
_stu = [[Student alloc]init];
self.stu.name = @"123";
[NSKeyedArchiver archiveRootObject:_stu toFile:[home stringByAppendingPathComponent:@"atany1.archiver"]];//归档
Student *stu1 = [NSKeyedUnarchiver unarchiveObjectWithFile:[home stringByAppendingPathComponent:@"atany1.archiver"]];//解档
NSLog(@"%@",stu1.name);