数据处理之文件读写

数据持久化的方式
1.属性列表property.plist
2.NSUserDefaults(偏好设置)
3.write to file(写入文件)
4.sqlite(iOS中的轻量级数据库)
5.CoreData(苹果基于sqlite封装的数据管理方式)

可视化的源码都是xml
documents:用来保存应用程序运行需要的持久化数据,通常是用户固定需要的数据,iTunes在自动备份时会自动备份此文件夹。

// 参数
// 1.主路径名称
// 2.当前用户(iOS端默认使用NSUserDomainMask)
// 3.是否使用绝对路径
// YES绝对路径-NO相对路径~(Domain领域,区域)
NSString *documentPath = [NSSearchPathForDirectoriesInDomains( 
                                           NSDocumentDirectory, 
                                           NSUserDomainMask, 
                                           YES) objectAtIndex:0];

library:通常用来存储当前应用程序运行期间需要的一些内存,包括缓存和偏好设置。

 NSString *libraryPath = NSSearchPathForDirectoriesInDomains(
                                           NSLibraryDirectory, 
                                           NSUserDomainMask, 
                                           YES)[0];   

caches:用来存放缓存文件,但是iTunes并不会备份此文件夹。

NSString *cachePath = [NSSearchPathForDirectoriesInDomains(
                                           NSCachesDirectory, 
                                           NSUserDomainMask,
                                           YES)firstObject];

preferences:用来存储应用的偏好设置,iTunes会自动备份此文件夹。

但是此文件夹不能被直接被寻找到,需要路径拼接,因为我们一般不会直接操作保存用户的偏好设置的内容,而是通过操作来使对应的代码生效,然后存储到这个文件夹。比如NSUserDefaults

NSString *preferencesPath = [NSSearchPathForDirectoriesInDomains(
                                           NSPreferencePanesDirectory, 
                                           NSUserDomainMask, 
                                           YES)firstObject];
NSLog(@"%@",preferencesPath);// 能打印出来但是没有此地址的数据

NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud setObject:@"游客" forKey:@"use_id"];
[ud setBool:YES forKey:@"NightModel"];
[ud setInteger:11 forKey:@"time"];

tmp:用来存放临时文件的文件夹。程序运行期间有可能里面的文件会时不时消失掉,所以永远不要使用此文件夹来存储需要持久化得数据。iTunes不会备份此文件夹。

NSString *tmpPath = NSTemporaryDirectory();

包文件

// 路径
NSString *bundlePath = [[NSBundle mainBundle]resourcePath];
NSLog( @"%@",bundlePath);
// 获取包内文件
NSString *imagePath = [[NSBundle mainBundle]pathForResource:@"12" ofType:@"jpg"];
UIImage *image =  [UIImage imageWithContentsOfFile:imagePath];

简单对象写入文件

1.字符串写入文件
NSString *incantation = @"I love my iOS teacher!";

NSString *path = [NSSearchPathForDirectoriesInDomains(
                                  NSDocumentDirectory,
                                  NSUserDomainMask, 
                                  YES)lastObject];
//path = [path stringByAppendingString:@"/a.txt"];//拼接地址文件

//path = [path stringByAppendingPathComponent:@"b.txt"];

path = [path stringByAppendingPathComponent:@"许晟馗@郝文举.avi"];
//写入文件
// 参数
// 1.路径,传入一个文件写入的地方,并且提供文件名称
// 2.YES为安全保护,在文件写入时如果中断了操作,那么操作恢复时可以保证文件的完整性。NO,不作任何保护。
// 3.数据写入文件的编码方式。
// 4.错误对象。
NSError *error = nil;
[incantation writeToFile:path 
              atomically:YES 
                encoding:NSUTF8StringEncoding 
                   error:&error];  
// 从文件中读取
NSString *result = [NSString stringWithContentsOfFile:path 
                                             encoding:NSUTF8StringEncoding
                                                error:nil];
NSLog(@"%@",result);
全局属性NSString *docPath;
self.docPath = [NSSearchPathForDirectoriesInDomains(
                                 NSDocumentDirectory, 
                                 NSUserDomainMask,
                                 YES)lastObject];  
2.数组写入文件
// 准备数组
NSArray *array = @[@1,@2,@3,@4];
// 准备即将写入的路径
NSString *path0 = [self.docPath stringByAppendingPathComponent:@"array"];
// 将数组写入路径
[array writeToFile:path0 atomically:YES];
// 根据路径读取数组
NSArray *resultArray = [NSArray arrayWithContentsOfFile:path0];
// 打印验证结果
NSLog(@"%@",resultArray);
3.字典写入
NSDictionary *dict = @{@"1":@"q",@"2":@"w",@"3":@"e"};

NSString *path1 = [self.docPath stringByAppendingPathComponent:@"dict"];

[dict writeToFile:path1 atomically:YES];

NSDictionary *resultDict = [NSDictionary dictionaryWithContentsOfFile:path1];

NSLog(@"%@",resultDict);
4.复杂对象写入文件
// 二进制流文件写入文件

UIImage *image0 = [UIImage imageNamed:@"12.jpg"];
// 使用JPEG的渲染方式将图片转化为二进制流
// 第一个参数为需要转化的图片,第二个为压缩比例,范围为0~1
// UIImagePNGRepresentation(UIImage * _Nonnull image)

NSData *data = UIImageJPEGRepresentation(image0, 1);

NSString *path2 = [self.docPath stringByAppendingPathComponent:@"aaa.jpg"];

[data writeToFile:path2 atomically:YES];
// 从文件中获取图片
UIImage *resultImage = [UIImage imageWithContentsOfFile:path2];
真正的深拷贝只有归档和反归档
SingleVip * s1 = [SingleVip new];
s1.name = @"张河山";
s1.age = 20;
s1.gender = @"male";

// 归档(将复杂对象转化为NSData的方式)

// 创建可变的二进制流用来存放即将转化的model数据
NSMutableData *mutdata = [NSMutableData new];
// 创建归档管理器,并制定要使用的可变二进制流控制器
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:mutdata];
// 归档操作(key值用于标记,方便饭归档时提取内容)
[archiver encodeObject:s1 forKey:@"s11"];
// 结束归当操作
[archiver finishEncoding];
// 写入文件
NSString *path6 = [self.docPath stringByAppendingPathComponent:@"s1"];
[mutdata writeToFile:path atomically:YES];

// 反归档

// 从文件中获取NSData数据
NSData *data0 = [NSData dataWithContentsOfFile:path6];
// 创建反归档管理器,并制定要获取的data数据来源
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc ]initForReadingWithData:data0];
// 反归档操作(根据归档时标记的key只操作)
SingleVip *s2 = [unarchiver decodeObjectForKey:@"s11"];
// 结束反归档
[unarchiver finishDecoding];
NSLog(@"%@-+-%@",s1,s2);
浅拷贝地址一样,就是两个指针指向同一地区,深拷贝地址不一样,是因为重新开辟地区放入相同事物
SingleVip * s1 = [SingleVip new];
SingleVip * s2 = [SingleVip new];

/*
  没有真正意义上的深拷贝,除了归档和反归档,
  因为可变数组的深拷贝虽然数组指针地址不同
  但是里面同一个元素(model)的地址还是一样。
*/
// 浅拷贝(不可变变不可变)
NSArray *array = @[s1,s2];
NSArray *_array = [array copy];
NSLog(@"%p-%p",array,_array);

// 深拷贝(不可变变可变)
NSArray *array1 = @[s1,s2];
NSMutableArray *mutArray = [array mutableCopy];
NSLog(@"%p-%p",array1,mutArray);
// 深拷贝(可变变不可变)
NSMutableArray *mutArray2 = [NSMutableArray arrayWithObjects:s1,s2, nil];
NSArray *array2 = [mutArray copy];// copy出的都是不可变的
NSLog(@"%p-%p",array2,mutArray2);
// 深拷贝(可变变可变)
NSMutableArray *mutArray3 = [mutArray2 mutableCopy];
NSLog(@"%p-%p",mutArray2,mutArray3);
    
SingleVip *s3 = [s1 copy];
NSLog(@"%p-%p",s1,s3);
SingleVip *s4 = [s1 mutableCopy];
NSLog(@"%p-%p",s1,s4);
点击方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    // 因为是单例,所以在程序的任何地方都可以获取
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
   // 可以获取存储在属性列表里面的值,然后作相应的操作
    if ([[ud objectForKey:@"use_id"] isEqualToString:@"游客"]) {
   
       NSLog(@"尊敬的用户请您登陆!");
    }
}

自定义的model类创建的复杂对象,无法响应writeToFile消息,不能直接写入文件。所以想要完成转化,需遵循NSCoding协议,实现两个编码方法。
在归档过程中,需要自定义实现归档的细节,将简单对象使用key值标记完成归档记录
在反归档过程中,同样需要根据归档记录时的标记来解码,完成属性值的对应

.h

#import 

@interface SingleVip : NSObject

@property(strong,nonatomic,nonnull)NSString  *name;
@property(assign,nonatomic)NSInteger  age;
@property(strong,nonatomic,nullable)NSString  *gender;

@end        

.m

#import "SingleVip.h"

@implementation SingleVip

// 归档(编码)
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    // 逐条
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInteger:_age forKey:@"age"];
    [aCoder encodeObject:_gender forKey:@"gender"];
}
// 反归档(解码)
- (instancetype)initWithCoder:(NSCoder *)aDecoder{

    if (self = [super init]) {
        _name = [aDecoder decodeObjectForKey:@"name"];
        _age = [aDecoder decodeIntegerForKey:@"age"];
        _gender = [aDecoder decodeObjectForKey:@"gender"];
    }

    return self;
}
// 要实现深浅拷贝,首先要遵循NSCopying协议,然后写一下方法->copyWithZone
/*
- (id)copyWithZone:(NSZone *)zone{
// 浅拷贝直接返回self
    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone{

    return self;
}
*/
- (id)copyWithZone:(NSZone *)zone{
    // 深拷贝
    id obj = [[[self class] allocWithZone:zone] init];

    return obj;
}

- (id)mutableCopyWithZone:(NSZone *)zone{

    // 深拷贝
    id obj = [[[self class] allocWithZone:zone] init];

    return obj;

}

@end  

你可能感兴趣的:(数据处理之文件读写)