首页 > 代码库 > 【学习ios之路:UI系列】iOS沙盒机制,文件读取,归档与反归档

【学习ios之路:UI系列】iOS沙盒机制,文件读取,归档与反归档

1.IOS中的沙盒机制

 IOS中的沙盒机制是一种安全体系,它规定了应用程序只能在为该应用创建的文件夹内读取文件,不可以访问其他地方的内容。所有的非代码文件都保存在这个地方,比如图片、声音、属性列表和文本文件等。

特点:

        1.每个应用程序都在自己的沙盒内

        2.不能随意跨越自己的沙盒去访问别的应用程序沙盒的内容

        3.应用程序向外请求或接收数据都需要经过权限认证

每个沙盒含有3个文件夹:Documents, Library 和 tmp。Library包含Caches、Preferences目录。如下图:

技术分享

Documents:苹果建议将程序创建产生的文件以及应用浏览产生的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录
Library:存储程序的默认设置或其它状态信息;

           Caches:存放缓存文件,保存应用的持久化数据,用于应用升级或者应用关闭后的数据保存,不会被itunes同步,所以为了减少同步的时间,可以考虑将一些比较大的文件而又不需要备份的文件放到这个目录下。
           Preferences:存储偏好设置,比如:应用程序是否是第一次启动,保存用户名和密码等

tmp:提供一个即时创建临时文件的地方,但不需要持久化,在应用关闭后,该目录下的数据将删除,也可能系统在程序不运行的时候清除。

 

2.获取上述文件夹的路径

①获取沙盒的路径

     NSLog(@"%@",NSHomeDirectory());
获取Documents目录路径:

   /*返回值是数组的原因:
             该方法一开始用于mac -os开发,对于PC端来说,可以有多个用户,所以获取时,会获取到所有用户的文件夹路径,
             但是该方法用于ios开发时,因为移动端只有一个用户,所以获取到的路径也只有一个. */
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);  
    NSString *documentsDirectory = [paths firstObject];  
获取Library目录路径:

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask, YES);  
    NSString *libraryDirectory = [paths objectAtIndex:0]; 
获取Cache目录路径:

 NSArray *cacPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, 
                                                            NSUserDomainMask, YES);  
 NSString *cachePath = [cacPath objectAtIndex:0]; 
获取Tmp目录路径:

 NSString *tmpDirectory = NSTemporaryDirectory();  
⑥创建文件和文件

     //创建文件夹
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);  
     NSString *documentsDirectory = [paths firstObject]; 
    NSFileManager *fileManager = [NSFileManager defaultManager];  
    NSString *testDirectory = [documentsDirectory stringByAppendingPathComponent:@"test"];  
    // 判断是否创建文件成功
    BOOL res=[fileManager createDirectoryAtPath:testDirectory withIntermediateDirectories:YES attributes:nil error:nil];      //<span style="font-family:georgia,verdana,Arial,helvetica,sans-seriff;">创建文件</span>    NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];    BOOL res=[content writeToFile:testPath atomically:YES encoding:   NSUTF8StringEncoding error:nil]; 


⑦删除文件
    NSFileManager *defaultManager = [NSFileManager defaultManager];
    if ([defaultManager isDeletableFileAtPath:filePath]) {
        [defaultManager removeItemAtPath:filePath error:nil];
    }
    //文件是否存在
      NSLog(%@, [fileManager isExecutableFileAtPath:filePath]?@"YES":@"NO");
⑧.NSUserDefaults

     //</span>程序运行时,判断用户是否登录
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSString *str = [userDefaults objectForKey:@"username"];
⑨NSBundle

   //应用程序包的路径,NSBundle,,应用程序加载所需的所有资源都存储在包中,而包也是上传到appStore的文件,
    从appstore下载的也是包,(包中资源是readonly的)
   NSString *boundlePath = [[NSBundle mainBundle] bundlePath];
   NSLog(@"%@",boundlePath);

3.文件写入和读取操作

 *  文件读取支持类型,(字符串,数组,字典,二进制数据NAData)
 * 1.写入文件
 *   writeToFile:atomically: --- 数组,字典,二进制数据,
 *   writeToFile:atomically:encoding:error:---字符串
 * 2.从文件读取数据
 *   [类名 + 类名WithContentsOfFile:]
 *   [NSArray + arrayWithContentsOfFile:]
 * 3.对于数组,字典大容器来说,想要实现文件读写,必须保证容器中的元素必须是字符串,数组,字典,
 *      二进制数据类型之一.
①获取文件路径

- (NSString *)filePath {
    //1.获取Documents文件夹路径
    //如要传入的3个参数(1)查找的文件夹的路径 (2)在那个范围查找 (3)是否显示详细路径
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask , YES);
    NSString *documentsDirectory = [paths firstObject];    
    //2.拼接上文件路径
    return [documentsDirectory stringByAppendingPathComponent:@"myDocument.txt"];
}
②字符串的写入和读取操作.

  //写入操作 
  NSString str = @"aad";
 BOOL isSuccess =[str  writeToFile:[self filePath] atomically:YES 
                                      encoding:NSUTF8StringEncoding error:&error];
  if (isSuccess) {
        NSLog(@"成功");
    } else {
        NSLog(@"失败");
    }
    
  //字符串从文件中读取数据
    NSString *text  = [NSString stringWithContentsOfFile:[self filePath] encoding:NSUTF8StringEncoding error:nil];
    self.tf2.text = text;

③数组的写入和读取操作

     //写入    
    NSArray *dataArr = @[@"aa", @"nn"];
    BOOL isSuccess = [dataArr writeToFile:[self filePath] atomically:YES];
 
      //读取
     NSArray *arr = [NSArray arrayWithContentsOfFile:[self filePath]];
④字典的写入和读取操作

    //写入
    NSDictionary *dic = @{@"name":@"zhang",@"hehe":@"dad"};
    BOOL isSuccess = [dic writeToFile:[self filePath] atomically:YES];
    
   //读取
  NSDictionary *dic =[NSDictionary dictionaryWithContentsOfFile:[self filePath]] ;

⑤NSData写入和读取文件

      //将字符串转为data型
     NSData *data = [@"dasf" dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
        //写入
      [data writeToFile:[self filePath] atomically:YES];
    
    //将data型转化为字符串
    NSString * newStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    //读写
    NSData *data1 =[NSData dataWithContentsOfFile:[self filePath]];
4.归档与反归档

 对象归档实例:Encoding

“归档”是值另一种形式的序列化,对模型对象进行归档的技术可以轻松将复杂的对象写入文件,然后再从中读取它们,只要在类中实现的每个属性都是基本数据类型(如int或float)或都是符合NSCoding协议的某个类的实例,你就可以对你的对象进行完整归档。

对,对象进行归档,服从协议<NSCoding>

NSCoding协议声明了两个方法:(required)

-(void)encodeWithCoder:(NSCoder *)aCoder,是将对象写入到文件中。 

-(id)initWithCoder:(NSCoder *)aDecoder,是将文件中数据读入到对象中。

实现这两个协议方法

1).创建Contact对象(Contact.h文件)

@interface Contact : NSObject <NSCoding>
//如果要对一个对象进行归档操作,需要让该类服从NSCoding协议
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *gender;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, copy) NSString *phone;

- (instancetype)initWithName:(NSString *)name gender:(NSString *)gender age:(NSInteger)age phone:(NSString *)phone;
@end
2).(Contact.m文件)实现协议

//当对一个对象进行归档时,自动调用该方法,为该对象的实例变量进行归档操作.
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeObject:_gender forKey:@"gender"];
    [aCoder encodeObject:_phone forKey:@"phone"];
    [aCoder encodeObject:@(_age) forKey:@"age"];

}
//当对于一个对象进行反归档时,自动调用该方法,为该对象的实例变量进行反归档.
- (id)initWithCoder:(NSCoder *)aDecoder {
    self  = [super init];
    if (self) {    
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.gender = [aDecoder decodeObjectForKey:@"gender"];
        self.age = [[aDecoder decodeObjectForKey:@"age"] integerValue];
        self.phone = [aDecoder decodeObjectForKey:@"phone"];
    }
    return self;
}
//初始化</span>
- (instancetype)initWithName:(NSString *)name gender:(NSString *)gender age:(NSInteger)age phone:(NSString *)phone {
    self = [super init];
    if (self) {
        self.name = name;
        self.gender = gender;
        self.age = age;
        self.phone = phone;
    }
    return self;
 }
3).实现归档操作

  
   Contact *contact = [[Contact alloc] initWithName:@"aa" gender:@"man" age:18 phone:@"138"]; 
    NSMutableData *mData = [NSMutableData data];
    //1.创建归档工具对象
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mData];
    //2.开始归档

    [archiver encodeObject:contact forKey:@"lock"];
    
    //3.结束归档
    [archiver finishEncoding];
    
    [contact release];
    [archiver release];

    //4.写入文件
   BOOL isSuccess = [mData writeToFile:[self getFilePath] atomically:YES];
    if (isSuccess) {
        NSLog(@"归档成功");
    } else {
        NSLog(@"归档失败");
    }
   //另一种方式
   //[NSKeyedArchiver archiveRootObject:contact toFile:[self getFilePath]];
4).反归档操作

    //1.从本地读取数据
    NSData *data = [NSData  dataWithContentsOfFile:[self getFilePath]];
    //2.创建反归档工具
    NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    //3.开始反归档操作
    Contact *contact = [unArchiver decodeObjectForKey:@"lock"];
    
    //结束反归档
    [unArchiver finishDecoding];
    [unArchiver release];
  //另一种方式:
    //Contact *contact = [NSKeyedUnarchiver unarchiveObjectWithFile:[self getFilePath]]; 



【学习ios之路:UI系列】iOS沙盒机制,文件读取,归档与反归档