• iOS进阶第一节 数据读写之文件读写


     

    一、沙盒机制

      1>. 每一个iOS程序都会问自己创建一个文件系统目录(文件夹),这个独立、封闭、安全的空间,叫做沙盒。

      注:①. 每一个应用程序都会拥有一个应用程序沙盒

        ②. 应用程序沙盒就是一个文件系统目录

      2>. 沙盒机制的特点

      ①. 沙盒是一种安全体系

      ②. 所有的非代码文件都保存在沙盒中,比如声音、图片、属性列表(plist)、sqlite数据库和文本文件等

      ③. 每个应用程序的活动范围都限定在自己的沙盒里,不能跨越沙盒去访问别的应用程序沙盒中的内容(iOS8已经部分开放)

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

      3>. 每个应用程序沙盒中都有三个文件夹(Documents、library、tmp)

    • Documents:保存应用程序运行时生成的需要持久化的数据,iTunes会自动备份该目录
    • Library/Caches:存放缓存文件,iTunes不会自动备份此目录,此目录下的文件不会在应用退出删除;一般存储体积加大,不是特别重要的资源。
    • Library/Preferences:保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息,iTunes会自动备份该目录
    • tmp:保存应用运行时所需的临时数据, 使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也有可能会清除该目录下的文件,iTunes不会同步该目录。iPhone重启时,该目录下的文件会被删除。

      4>. 获取应用程序及三个文件目录的代码:

        // 获取当前应用程序的沙盒根目录
        NSString *rootPath = NSHomeDirectory();
        NSLog(@"rootPath is %@", rootPath);
        
        // 定位根目录下的所有文件的目录
        // 1、Documents
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSLog(@"documentsPath is %@", documentsPath);
        
    //    NSString *documentsPath1 = [rootPath stringByAppendingString:@"/Documents"];
        NSString *documentsPath1 = [rootPath stringByAppendingPathComponent:@"Documents"];
        NSLog(@"documentsPath1 is %@", documentsPath1);
        
        // 2、Library
        NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
        NSLog(@"libraryPath is %@", libraryPath);
    
        // 3、Library之Caches
        NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        NSLog(@"cachePath is %@", cachePath);
    
        // 4、library之Preferences
        NSString *preferencesPath = [libraryPath stringByAppendingPathComponent:@"preferences"];
        NSLog(@"preferencesPath is %@", preferencesPath);
    
        // 5、tmp
        NSString *tmpPath = NSTemporaryDirectory();
        NSLog(@"tmpPath is %@", tmpPath);

     二、简单对象的读写(I/O)操作

      1>. iOS提供了4种类型的数据可以直接进行文件存取:

      NSString/NSMutableString(字符串)

      NSArray/NSMutableArray(数组)

      NSDictionary/NSMutableDictionary(字典)

      NSData/NSMutableData(数据)

      注:数组和字典中元素对象的类型,也必须是上述四种,否则不能直接写入文件。

      2>. 相应的读写代码:

        // 字符串写入沙盒
        // 在Ducuments下面创建一个文本路径,假设文本名称为bada.txt
        NSString *txtPath = [documentsPath stringByAppendingPathComponent:@"bada.txt"]; // 此时仅存在路径,文件并没有真实存在
        NSString *string = @"中二洪荒巴达之力";
        
        // 字符串写入时执行的方法
        [string writeToFile:txtPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
        NSLog(@"txtxPath is %@", txtPath);
        
        // 字符串读取的方法
        NSString *resultString = [NSString stringWithContentsOfFile:txtPath encoding:NSUTF8StringEncoding error:nil];
        NSLog(@"resultString is %@", resultString);
        
        // 数组写入文件
        // 创建一个存储数组文件路径
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"girl.txt"];
        NSArray *array = @[@"姜丽玲", @"王六六", @"胡洁佩", @"戴苗苗", @"莫大宝", @"朱珍洁", @"秋香"];
        
        // 数组写入文件的方法
        [array writeToFile:filePath atomically:YES];
        NSLog(@"filePath is %@", filePath);
        
        // 从文件中间读取数组的方法
        NSArray *resultArray = [NSArray arrayWithContentsOfFile:filePath];
        NSLog(@"%@", resultArray[1]);
        
        // 字典写入文件
        // 创建一个存储字典文件路径
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"love.txt"];
        NSDictionary *dictionary = @{@"巴达":@"秋香", @"张不慌":@"王六六"};
        
        // 字典写入文件的方法
        [dictionary writeToFile:filePath atomically:YES];
        NSLog(@"filePath is %@", filePath);
        
        // 从文件中间读取字典的方法
        NSDictionary *resultDictionary = [NSDictionary dictionaryWithContentsOfFile:filePath];
        NSLog(@"%@", resultDictionary);
        
        
        // NSData写入文件
        // 创建一个存放NSData数据的路径
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"baby.txt"];
        // 得到一个UIImage对象
        UIImage *image = [UIImage imageNamed:@"5"];
        
        // 将UIImage对象转换成NSData对象
        NSData *data = UIImagePNGRepresentation(image);
        
        // data写入文件的方法
        [data writeToFile:filePath atomically:YES];
        NSLog(@"filePath is %@", filePath);
        
        // 从文件读取存储的NSData数据
        NSData *resultData = [NSData dataWithContentsOfFile:filePath];
        
        // 将得到的NSData数据转换成原有的图片对象
        UIImage *resultImage = [UIImage imageWithData:resultData];
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
        imageView.image = resultImage;
        [self.view addSubview:imageView];

      注:每一种类型单独执行!

    三、文件管理器(NSFileManager)和文件对接器(NSFileHandle)

      1>. 两者的区别:

      文件管理器主要是对文件进行的操作(创建、删除、改名等)以及文件信息的获取;

      而文件连接器主要是对文件内容进行读取和写入操作。

      2>. 文件管理器(NSFileManager)应用

      ①. 创建文件及简单操作代码:

    - (IBAction)createFile:(id)sender {
        // 得到Documents路径
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        // 创建一个文件路径
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"qiuxiang.txt"];
        // 创建文件需要一个文件管理对象
        NSFileManager *fileManager = [NSFileManager defaultManager];
        // 创建文件
        [fileManager createFileAtPath:filePath contents:[@"bada" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
        NSLog(@"%@", filePath);
        
        // 获取某个文件或者某个文件夹的大小
        NSDictionary *dic = [fileManager attributesOfItemAtPath:filePath error:nil];
        NSLog(@"%@", dic);
        NSNumber *number = [dic objectForKey:NSFileSize];
        NSLog(@"%@", number);
        
    }

      ②. 创建目录(文件夹)代码:

    - (IBAction)createDirectory:(id)sender {
        // 找到caches的路径
        NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        // 创建的文件夹的路径
        NSString *directoryPath = [cachesPath stringByAppendingPathComponent:@"downlondImages"];
        // 创建文件需要一个管理对象
        NSFileManager *fileManager = [NSFileManager defaultManager];
        // 创建文件夹
        [fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil];
        NSLog(@"%@", directoryPath);
        
    }

      ③. 应用实例代码:

    /* 
    在Documents文件夹下,创建一个文件夹(path),在该文件夹下创建一个文件(test.txt),将一个图片对象存入到该文件中,
    然后在Caches文件夹下创建一个文件夹名为"testDirectroy",将test.txt文件移动到这个文件夹下.  
    */ - (IBAction)test1:(id)sender { // 在Documents文件夹下,创建一个文件夹(path),在该文件夹下创建一个文件(test.txt),将一个图片对象存入到该文件中 NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSString *path = [docPath stringByAppendingPathComponent:@"path"]; NSFileManager *fileManager = [NSFileManager defaultManager]; [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil]; NSString *testPath = [path stringByAppendingPathComponent:@"test.txt"]; UIImage *image = [UIImage imageNamed:@"5"]; NSData *data = UIImagePNGRepresentation(image); [fileManager createFileAtPath:testPath contents:data attributes:nil]; NSLog(@"%@",testPath); //然后在Caches文件夹下创建一个文件夹名为"testDirectroy" NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString *dirPath = [cachePath stringByAppendingPathComponent:@"testDirectroy"]; [fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:nil]; NSLog(@"dirPath is %@",dirPath); //移动 NSString *desPath = [dirPath stringByAppendingPathComponent:@"baby.txt"]; [fileManager moveItemAtPath:testPath toPath:desPath error:nil]; }

      3>. 文件对接器(NSFileHandle)

      ①. NSFileHandle是非常基础的只针对文件内容的操作(写入、读取、根性),是把NSData通过连接器一个字节一个字节的写入/读取文件(NSData <——> NSFileHandle <——> 文件)。

      ②. 使用场景:对文件内容进行局部的修改、追加内容。

      ③. 使用步骤:1). 文件对接并获取一个NSFileHandle对象;  

              2). 读写操作;

              3).关闭对接。

      注:NSFileHandle类并没有提供创建文件的功能,必须使用NSFileManager的方法来创建文件,因此,在使用NSFileHandle的特有方法时,到要保证文件已经存在,否则返回nil。

      4>. 应用实例代码:

    /*
     练习要求:从一个文件中指定的位置开始追加内容
     提示:
       1、在documents目录下创建一个test.txt文件,文件中的内容为"abcdefg"
       2、从文件偏移量为3那个位置开始追加内容"1234"
     */
    - (void)change {
        // 获取Documents路径
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        // 创建文件路径
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"test.txt"];
        // 使用文件管理对象创建文件
        NSFileManager *fileManager = [NSFileManager defaultManager];
        [fileManager createFileAtPath:filePath contents:[@"abcdefg" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
        // 创建文件对接对象
        NSFileHandle *habdle = [NSFileHandle fileHandleForUpdatingAtPath:filePath]; // 文件对接对象此时针对文件,既可以读取,也可以写入
        // 将偏移量挪到3的文字
        [habdle seekToFileOffset:3];
        // 写入数据
        [habdle writeData:[@"1234" dataUsingEncoding:NSUTF8StringEncoding]];
        // 执行完后关闭文件
        [habdle closeFile];
        
        NSLog(@"%@", filePath);   
    }

     

    四、复杂对象的读写(I/O)操作

      1>. 复杂对象就是在Foundation框架内不存在的数据类,

            如:自定义的Person类无法在程序内通过 writerToFile: 这个方法写入文件内。

      2>. 复杂对象只能通过 将复杂对象转换为NSData(这个步骤就是归档),然后再通过 writerToFile: 方法写入文件

            来进行数据持久化

      3>. 从文件中读取复杂对象是 从文件中读取NSData数据,然后再将NSData转换为复杂对象(这个过程就是反归档)。

      注:①. 复杂对象写入文件的过程:复杂对象 —> 归档 —> NSData —> writeToFile;

        ②. 从文件中读取复杂对象的过程:读取文件   NSData   反归档   复杂对象。

      4>. 归档和反归档实例(以Person对象为例)

      ①. 首先,要遵守NSCoding协议:

    @interface Person : NSObject <NSCoding>
    @property (copy, nonatomic) NSString *name; @property (copy, nonatomic) NSString *age; @property (copy, nonatomic) NSString *gender;

    - (instancetype)initWithName:(NSString *)name age:(NSString *)age gender:(NSString *)gender;
    @end

      ②. 其次,实现协议里的两个方法:

    // 对Person对象进行归档时,此方法执行。
    // 对Person中想要进行归档的所有属性,进行序列化操作

    - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.name forKey:@"name"]; [aCoder encodeObject:self.age forKey:@"age"]; [aCoder encodeObject:self.gender forKey:@"gender"]; }
    // 对Person对象进行反归档时,此方法执行。
    // 创建一个新的Person对象,所有属性都是通过反序列化得到的
    - (id)initWithCoder:(NSCoder *)aDecoder {
        NSString *name = [aDecoder decodeObjectForKey:@"name"];
        NSString *age = [aDecoder decodeObjectForKey:@"age"];
        NSString *gender = [aDecoder decodeObjectForKey:@"gender"];
        return [self initWithName:name age:age gender:gender];
    }

      ③. 具体操作代码:

    // 归档
    - (IBAction)archive:(id)sender {
        
        // 创建两个人
        Person *bada = [[Person alloc] initWithName:@"bada" age:@"22" gender:@""];
        Person *qiuxiang = [[Person alloc] initWithName:@"qiuxiang" age:@"18" gender:@""];
        
        // 获取Documents路径
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        // iOS中的归档类是NSKeyedArchiver,这个类的作用是将复杂对象转换成NSData对象
        // 创建一个可变数据对象
        NSMutableData *mData = [NSMutableData data];
        NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mData];
        
        // 归档时要给归档对象加标记
        [archiver encodeObject:bada forKey:@"yadang"];
        [archiver encodeObject:qiuxiang forKey:@"xiawa"];
        
        [archiver finishEncoding]; // 结束归档,不管还有多少未归档的归档对象,都不会执行归档操作
        
        // 将数据写入文件
        // 创建文件路径
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"bada.qiuxiang"];
        [mData writeToFile:filePath atomically:YES];
    }
    
    // 反归档
    - (IBAction)unArchiver:(id)sender {
        
        // 获取到存放数据的路径
        // 获取Documents路径
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"bada.qiuxiang"];
        // 获取NSData对象
        NSData *data = [NSData dataWithContentsOfFile:filePath];
        
        // iOS中的解档类是NSKeyedUnarchiver,TA的作用是讲NSData对象还原成原本的复杂对象
        NSKeyedUnarchiver *unarchibver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        // 解档
        Person *person = [unarchibver decodeObjectForKey:@"yadang"];
        
        NSLog(@"name is %@, age is %@, gender is %@", person.name, person.age, person.gender);   
    }
  • 相关阅读:
    POJ 2240 Arbitrage spfa 判正环
    POJ 3259 Wormholes spfa 判负环
    POJ1680 Currency Exchange SPFA判正环
    HDU5649 DZY Loves Sorting 线段树
    HDU 5648 DZY Loves Math 暴力打表
    HDU5647 DZY Loves Connecting 树形DP
    CDOJ 1071 秋实大哥下棋 线段树
    HDU5046 Airport dancing links 重复覆盖+二分
    HDU 3335 Divisibility dancing links 重复覆盖
    FZU1686 神龙的难题 dancing links 重复覆盖
  • 原文地址:https://www.cnblogs.com/hyl2012/p/5223136.html
Copyright © 2020-2023  润新知