美文网首页
02、文件管理器、文件对接器与复杂对象的读写操作

02、文件管理器、文件对接器与复杂对象的读写操作

作者: 深爱久随i | 来源:发表于2016-12-08 20:10 被阅读0次

    一、文件管理器与文件连接器

    1、文件管理器(NSFileManger),主要是对文件进行创建,删除,改名以及文件信息的获取操作。
    以下是有关NSFileManger的方法

    #pragma mark-------有关NSFileManager的方法
    -(void)myFileManger{
        //获取文件管理对象
        NSFileManager* fileManger=[NSFileManager defaultManager];
        //创建文件,并写入数据 如果该方法的返回值为YES,文件创建成功或者文件已经存在  NO:文件创建失败
        //第一个参数:要创建文件的路径
        //第二个参数:要写入文件的内容
        //第三个参数:设置文件的用户组,权限,修改时间等设置,如果赋值为nil,系统就会自己为文件加一些默认设置
        //创建文件路径
        NSString *path=[[SandBoxPaths cachesPath] stringByAppendingString:@"/array.json"];
        //创建要写入的内容
        NSArray* array=@[@"王",@"余",@"雷"];
        NSData* arrayData=[NSJSONSerialization dataWithJSONObject:array options:(NSJSONWritingPrettyPrinted) error:nil];
        //判断文件是否创建成功
       BOOL isSuccess= [fileManger createFileAtPath:path contents:arrayData attributes:nil];
        if (isSuccess) {
            NSLog(@"cachesPath-----%@",[SandBoxPaths cachesPath]);
        }
        else{
            NSLog(@"失败");
        }
        
        //读取数据
        //先判断该路径下文件是否存在
        BOOL isExists=[fileManger fileExistsAtPath:path];
        if (isExists) {
            //存在
            NSData* readData=[fileManger contentsAtPath:path];
            NSArray* readArray=[NSJSONSerialization JSONObjectWithData:readData options:(NSJSONReadingAllowFragments) error:nil];
            NSLog(@"读取出来的----%@",readArray);
        }
        else{
            NSLog(@"该路径下文件不存在");
        }
        
        //将cachesPath中的array.json文件移动到documents文件下  原有文件已经移动到了新的文件夹下,源文件已经不存在了.相当于剪切
        BOOL isMove=[fileManger moveItemAtPath:path toPath:[[SandBoxPaths documentPath] stringByAppendingString:@"/newarray.json"] error:nil];
        if (isMove) {
            NSLog(@"移动成功");
        }
        else{
            NSLog(@"失败");
        }
        
        
        //将原有路径下的文件拷贝到documents文件下,相当于复制
        BOOL isCopy=[fileManger copyItemAtPath:path toPath:[[SandBoxPaths documentPath] stringByAppendingString:@"/copyarray.json"] error:nil];
        if (isCopy) {
            NSLog(@"copy成功");
        }
        else{
            NSLog(@"失败");
        }
        
        //比较文件内容
       BOOL isEqual= [fileManger contentsEqualAtPath:path andPath:[[SandBoxPaths documentPath] stringByAppendingString:@"/copyarray.json"]];
        if (isEqual) {
            NSLog(@"文件内容相同");
        }
        else{
            NSLog(@"文件内容不同");
        }
        
        BOOL isRemove=[fileManger removeItemAtPath:[[SandBoxPaths documentPath] stringByAppendingString:@"/copyarray.json"] error:nil];
        if (isRemove) {
            NSLog(@"删除成功");
        }
        else{
            NSLog(@"失败");
        }
        //创建文件夹
        // 第一个参数:要创建的文件夹的路径
        //第二个参数:YES:如果父目录(文件夹)不存在,创建的时候会将父目录一起创建;NO:如果父目录不存在,那么文件夹就会创建失败
        //第三个参数: 文件夹的权限
       BOOL isCreat = [fileManger createDirectoryAtPath:[[SandBoxPaths homePath] stringByAppendingString:@"/newPath/aaa"] withIntermediateDirectories:YES attributes:nil error:nil];
        if (isCreat) {
            NSLog(@"创建成功");
        }
        else{
            NSLog(@"失败");
        }
    }
    

    2、文件连接器(NSFileHandle),主要是对文件的内容进行读取、写入和更新操作。主要应用场景在对文件的内容进行局部修改,替换某些内容,有些地方说是追加内容,但我试了好几遍,验证了seekToFileOffset该方法是在指定偏移量后进行替换该位置的内容,而不是追加,望各位简友多多注意这一点。
    以下是有关NSFileHandle的方法

    #pragma mark-------有关NSFileHandle的方法
    //NSFileHandle的使用
    -(void)myFileHandle{
       //获取文件管理对象
       NSFileManager* manger=[NSFileManager defaultManager];
       NSString* path=[[SandBoxPaths documentPath] stringByAppendingString:@"/text.txt"];
       BOOL isExists=[manger fileExistsAtPath:path];
       if (!isExists) {
          //文件不存在,则创建
           [manger createFileAtPath:path contents:nil attributes:nil];
       }
      //对文件内容进行操作
      // 向文件写入内容
         NSFileHandle* handle=[NSFileHandle fileHandleForWritingAtPath:path];
       NSString* inputString=@"yufei";
       NSData* inputData=[inputString dataUsingEncoding:NSUTF8StringEncoding];
       [handle writeData:inputData];
       //操作完毕要关闭文件
       [handle closeFile];
    
       //更新数据
       NSFileHandle* updateHandle=[NSFileHandle fileHandleForUpdatingAtPath:path];
       //我们要从余之后写入数据,我们就需要将文件偏移量设置为1,然后再写入。相当于从1位置开始将后面的字符或内容进行替换
       [updateHandle seekToFileOffset:1];
       NSString* updateString=@".qqq";
       NSData* updateData=[updateString dataUsingEncoding:NSUTF8StringEncoding];
       [updateHandle writeData:updateData];
         //操作完毕要关闭文件
       [updateHandle closeFile];
       
       //读取数据
       NSFileHandle* readHandle=[NSFileHandle fileHandleForReadingAtPath:path];
       //设置要读取多长的内容
    //    NSData* readData=[readHandle readDataOfLength:3];
       NSData* readData=[readHandle readDataToEndOfFile];
        [readHandle closeFile];
       NSString* readString=[[NSString alloc] initWithData:readData encoding:NSUTF8StringEncoding];
       NSLog(@"readString---%@",readString);
    
       
    }
    

    该代码中还差一些方法,我已经截图给大家了,若对各位有帮助可以看一下

    屏幕快照 2016-12-08 下午7.35.10.png
    屏幕快照 2016-12-08 下午7.35.33.png

    *两者的区别就是NSFileManger针对文件进行操作,而NSFileHandle则针对文件中的内容进行操作。

    二、复杂对象的读写操作

    1、首先我们需要明白什么是复杂对象,简单来说就是在Foundation框架内不存在的数据类,比如:自定义的Person类,Student类都属于复杂对象,如果想要将这些类通过writeToFile方法写入到文件夹内是不可以的,那么应该怎么办呢,这就需要归档与反归档了。

    • 归档:就是将复杂对象转换为NSData以达到数据持久化的目的,这就是归档,本质就是将复杂对象写入文件。
    • 反归档:就是从文件中读取NSData数据,将NSData转换为复杂对象,这就是反归档,本质就是读取文件的过程。
      在这里给大家做一个示范,请看下面的代码

    先在工程中将一个Person类,在Person.h中遵循协议,并声明两个属性。


    屏幕快照 2016-12-08 下午7.51.00.png

    然后在Person.m实现协议里面的两个方法

    @implementation Person
    //归档的过程,相当于将复杂对象转换为NSData类型,是为了写入文件
    -(void)encodeWithCoder:(NSCoder *)aCoder{
        //归档的过程是将当前对象每一个属性都进行编码
        //第一个参数:要进行编码的属性的值
        //第二个参数:为属性的值添加标记,是为了解码使用
        [aCoder encodeObject:self.name forKey:@"name"];
        [aCoder encodeInteger:self.age forKey:@"age"];
        NSLog(@"执行了归档的方法");
    }
    //反归档的过程,相当于将NSData转换为复杂对象,是为了读取使用
    //也是一个初始化方法
    -(id)initWithCoder:(NSCoder *)aDecoder{
        NSLog(@"执行了反归档的方法");
    
        self=[super init];
        if (self) {
            //解码  从文件中读取出来值,赋值给对应的属性
            self.name=[aDecoder decodeObjectForKey:@"name"];
            self.age=[aDecoder decodeIntegerForKey:@"age"];
        }
        return self;
    }
    @end
    

    然后在ViewController.m中进行归档与反归档操作

    //归档的过程
    -(void)myEncoder{
       //需要创建一个Person对象
       Person* person=[[Person alloc] init];
       person.name=@"余菲";
       person.age=18;
       //需要创建一个可变的NSData对象,用来存放归档好的person对象
       NSMutableData* mData=[NSMutableData data];
       //创建一个归档工具
       //参数为要承接归档完成的复杂对象
       NSKeyedArchiver* archiver=[[NSKeyedArchiver alloc] initForWritingWithMutableData:mData];
       //归档
       //第一个参数:要归档的复杂对象
       //第二个参数:标记,为了反归档使用
       [archiver encodeObject:person forKey:@"person"];
       //归档结束,一定要调用下面这个方法,要不然mData中不会有值
       [archiver finishEncoding];
       //将mData持久化到本地
       NSString* Path=[[SandBoxPaths documentPath] stringByAppendingPathComponent:@"person.data"];
       [mData writeToFile:Path atomically:YES];
       NSLog(@"---%@",mData);
    }
    
    // 反归档的过程
    -(void)myDecode{
        //将刚才归档文件的data数据读取出来,以便反归档使用
         NSString* Path=[[SandBoxPaths documentPath] stringByAppendingPathComponent:@"person.data"];
        NSData* data=[NSData dataWithContentsOfFile:Path];
        //初始化一个反归档对象
        //参数:要反归档的data对象
        NSKeyedUnarchiver* unarchiver=[[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        //反归档
        Person* per_1=[unarchiver decodeObjectForKey:@"person"];
        // 反归档结束的方法,必须调用
        [unarchiver finishDecoding];
        NSLog(@"name---%@,age---%ld",per_1.name,(long)per_1.age);
            
    }
    
    • 在这里面需要注意的就是在归档与反归档操作完成之后一定要记得调用finishDecoding方法结束操作。
    • 在这里有些人会问,为什么不直接将复杂对象的类进行归档呢,而是要对其中的一个个属性进行编码呢?有可能大家会忽略一点,那就是有些属性也会是一个复杂对象,这时就会出现问题,所以归档时必须将当前对象每一个属性都进行编码,而在反归档时,必须挨个解码。

    在这里给大家简单的提一下NSUserDefaults

     //NSUserDefaults 存储到prefenrences文件夹下,在该文件夹下以plist格式存在 只能存储简单对象!!!!
        [[NSUserDefaults standardUserDefaults] setObject:@"余菲" forKey:@"name"];
        NSDictionary* dic=@{@"特点":@"乖巧可爱",@"年龄":@"芳龄18"};
        [[NSUserDefaults standardUserDefaults] setObject:dic forKey:@"property"];
        //删除
    //    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"property"];
        //获取存储的值
        NSString* name=[[NSUserDefaults standardUserDefaults] objectForKey:@"name"];
        NSLog(@"name---%@",name);
        NSLog(@"preferencesPath-----%@",[SandBoxPaths  preferencesPath]);
    
    屏幕快照 2016-12-08 下午8.06.40.png

    希望对各位简友有所帮助-----

    相关文章

      网友评论

          本文标题:02、文件管理器、文件对接器与复杂对象的读写操作

          本文链接:https://www.haomeiwen.com/subject/ysbsmttx.html