沙盒机制
沙盒的概念
沙盒是每一个iOS应用程序都会自动创建的一个文件系统目录(文件夹),而且沙盒还具有独立、封闭、安全的特点。
-
模拟器沙盒的位置
/User/userName/Library/Application Support/iPhone Simulator
-
当我们创建应用程序时,在每个沙盒中含有三个文件,分别是Document、Library和temp。
- Document:一般需要持久的数据都放在此目录中,可以在当中添加子文件夹,iTunes备份和恢复的时候,会包括此目录。
-
Library:设置程序的默认设置和其他状态信息,iTunes会自动备份该文件目录
- Library/Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出时删除,通常存放体积比较大,但并不是很重要的资源
- Library/Preferences:保存应用的所有偏好设置,iOS的Setting(设置)应用会在该目录中查找应用的设置信息,iTunes会自动备份该目录。——PS:如果你想对偏好设置进行相应的操作,应该使用NSUserDefaults类来取得和设置应用程序的偏好,而不是直接创建偏好设置文件
- temp:创建临时文件的目录,当iOS设备重启时,文件会被自动清除
获取沙盒目录
-
获取程序的根目录(home目录)
NSString *homePath = NSHomeDirectory()
-
获取Document目录
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMark,YES); NSString *docPath = [paths lastObject];
-
获取Library目录
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMark,YES); NSString *docPath = [paths lastObject];
-
获取Library中的Cache
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCacheDirectory,NSUserDomainMark,YES); NSString *docPath = [paths lastObject];
-
获取temp路径
NSString *docPath = NSTemporaryDirectory();
NSString类路径处理方法和IO操作
-
文件路径的处理
举例:NSString *path = @"/Uesrs/apple/testfile.txt"
-
获得组成此路径的各个组成部分
方法:- (NSArray *)pathComponents; [path pathComponents]; 结果: ("/","User","apple","testfile.txt")
-
提取路径的最后一个组成部分
方法:- (NSString *)lastPathComponents; [path lastPathComponents]; 结果: testfile.txt
-
删除路径的最后一个组成部分
方法:- (NSString *)stringByDeletingLastPathComponent; [path stringByDeletingLastPathComponent]; 结果: /Users/apple
-
将path添加到前面路径的末尾
方法:- (NSString *)stringByAppendingPathComponent:(NSString *)str; [path stringByAppendingPathComponent:@"app.txt"]; 结果: /Users/apple/testfile.txt/app.txt
-
取路径最后部分的扩展名
方法:- (NSString *)pathExtension; [path pathExtension]; 结果: txt
-
删除路径最后部分的扩展名
方法:- (NSString *)stringByDeletingPathExtension; [path stringByDeletingPathExtension]; 结果: /Users/apple/testfile
-
路径最后部分追加扩展名
方法:- (NSString *)stringByAppendingPathExtension:(NSString *)str; [path stringByAppendingPathExtension:@"jpg"]; 结果: /User/apple/testfile.txt.jpg
-
NSString的写入与读取(I/O)
//创建保存路径 NSString *textPath = [docPath stringByAppendingPathComponents:@"objc.txt"]; NSString *string = @"Objective-C" //字符串写入时执行的方法 [string writeToFile:textPath automatically:YES encoding:NSUTF8StringEncoding error:nil]; //读取字符串方法 NSString *resultStr = [NSString stringWithContentsOfFile:textPath encoding:NSUTF8StringEncoding error:nil]; NSLog(@"resultStr is %@", resultStr);
NSData和I/O
NSData是用来包装数据的,NSData存储的是二进制数据,屏蔽了数据之间的差异,文本、音频、图像等数据都可用NSData来存储。
NSData的写入与读取(I/O)
// NSData写入文件
// 创建一个存放NSData数据的路径
NSString *fileDataPath = [docPath stringByAppendingPathComponent:@"icon"];
// 得到一个UIImage对象
UIImage *image = [UIImage imageNamed:@"icon.jpg"];
// 将UIImage对象转换成NSData对象
NSData *data = UIImageJPEGRepresentation(image, 0);
[data writeToFile:fileDataPath atomically:YES];
NSLog(@"fileDataPath is %@", fileDataPath);
// 从文件读取存储的NSData数据
NSData *resultData = [NSData dataWithContentsOfFile:fileDataPath];
// 将得到的NSData数据转换成原有的图片对象
UIImage *resultImage = [UIImage imageWithData:resultData];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
imageView.image = resultImage;
[self.view addSubview:imageView];
NSString 与 NSData
-
NSData-> NSString
NSString * aStr = [[NSString alloc] initWithData:aData encoding:NSUTF8StringEncoding];
-
NSString->NSData
NSString * aStr = @"12345abcd"; NSData *aData = [aStr dataUsingEncoding:NSUTF8StringEncoding];
-
将data类型的数据,转成UTF8的数据
+ (NSString *)dataToUTF8String:(NSData*)data { NSString * buf = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; return buf; }
-
将string转换为指定编码
+ (NSString *)changeDataToEncodingString:(NSData *) encoding:(NSStringEncoding)encodeing { NSString * buf = [[NSString alloc]initWithData:data encoding:encoding]; return buf; }
UIImage 与 NSData
-
UIImage->NSData
UIImage *image = [UIImage imageNameed:@"Highest.jpg"]; NSData *imageData = UIImageJPEGRepresentation(image,0.5);//第二个参数:CGFloatcompressionQuality - 压缩质量, 范围在0~1之间, 1代表是100%不压缩 NSString * imagePath = [documentsPath stringByAppendingPathComponents:@"image.jpg"]; [imageData writeToFile:imagePath atomically:YES];
-
NSData-> UIImage
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
NSArray的写入与读取(I/O)
NSString *filePath = [docPath stringByAppendingPathComponent:@"language.txt"];
NSArray *array = @[@"C语言", @"JAVA",@"Objective-C", @"Swift", @"PHP", @"C++"];
//数组写入文件
[array writeToFile:filePath atomically:YES];
NSArray *resultArr = [NSArray arrayWithContentsOfFile:filePath];
NSLog(@"%@", resultArr[1]);
NSDictionary的写入与读取(I/O)
NSString *filePath = [docPath stringByAppendingPathComponent:@"love,txt"];
NSDictionary *dic = @{@"职业":@"程序员", @"梦想":@"代码无BUG"};
//字典写入文件
[dic writeToFile:filePath atomically:YES];
NSDictionary *resultDic = [NSArray arrayWithContentsOfFile:filePath];
NSLog(@"%@", resultDic[@"梦想"]);
文件管理
-
文件管理器与文件连接器之间的区别
- 文件管理器主要是对文件进行操作(创建、删除、改名等)以及文件信息的获取
- 文件连接器主要是对文件内容进行读取与写入操作
NSFileManager
-
创建文件管理
NSFileManager * fileManager = [NSFileManager defaultManager]; NSString *path = [NSHomeDirectory( ) stringByAppendingPathComponent:@"holyBible.txt"];
-
创建一个文件并写入数据
NSString *text = @"我是一个文件"; NSData *data = [text dataUsingEncoding: NSUTF8StringEncoding]; //方法:- (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data attributes:(NSDictionary *)attr; BOOL success = [fileManager createFileAtPath:path contents:data attributes:nil];
-
从一个文件中读取数据
NSData* data = [fileManager contentsAtPath:filePath];
-
移动文件
//scrPath路径上的文件移动到dstPath路径上,注意这里的路径**是文件路径而不是目录** NSString *toPath = [NSHomeDirectory( ) stringByAppendingPathComponent:@"hellogod/New Testament.txt"]; [fileManager createDirectoryAtPath:[toPath stringByDeletingLastPathComponents] withIntermediateDirecotries:YES attributes:nil error:nil]; NSError *error; BOOL isSuccess = [fileManager moveItemAtPath:filePath toPath:toPath error:&error];
-
复制文件(重命名)
//scrPath路径上的文件复制到dstPath路径上 NSString *copyPath = [NSHomeDirectory( ) stringByAppendingPathComponent:@"备份/Old Testament.txt"]; [fileManager createDirectoryAtPath:[toPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; BOOL success = [fm copyItemAtPath:filePath toPath:copyPath error:nil];
-
比较两个文件的内容是否一样
- (BOOL)contentsEqualAtPath:(NSString *)path andPath:(NSString*)otherPath;
-
移除文件
- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error;
-
文件是否存在
//- (BOOL)fileExistsAtPath:(NSString *)path; if([fm fileExistsAtPath]){ if ([fm removeItemAtPath:copyPath]){ NSLog(@"remove success"); } }
-
获取目录文件信息
NSString *enuPath = [NSHomeDirectoty( ) stringByAppendingPathComponent:@"Test"]; NSDictionaryEnumerator *dirEnum = [fileManager enumeratorAtPath:enuPath]; NSString *path = nil; NSDirectoryEnumerator<NSString *> * dirEnum = [fileManager enumeratorAtPath:enuPath]; while ((path = [dirEnum nextObject]} != nil) { NSLog(@"%@",path); }
NSFileHandle
Objective-C使用NSFileHandle类对文件进行基本操作,iOS文件操作.
NSFileHandle类中得方法可以对文件进行基本的读写,偏移量的操作。
-
NSFileHandle基本步骤:
- 1、打开文件,获取一个NSFileHandle对象。
- 2、对打开NSFileHandle的文件对象行I/O操作
- 3、关闭文件对象
+(NSFileHandle)fileHandleForReadingAtPath:path 打开一个文件用于读入
+(NSFileHandle)fileHandleForWritingAtPath:path 打开一个文件用于写入
+(NSFileHandle)fileHandleForUpdatingAtPath:path 打开一个文件用于读写
-(NSData)availableData 从设备或者通道返回可用数据
-(NSData)readDataToEndOfFile 读取其余的数据知道文件的末尾(最多UINT_MAX字节)
-(NSData)readDataOfLength:(NSUInteger)bytes 从文件中读取指定字节的内容
-(void)writeData:data 将data写入文件
-(unsigned long long)offsetInFile 获取当前偏移量
-(void)seekToFileOffset:offset 设置偏移量
-(unsigned long long)seekToEndOfFile 将偏移量定位到文件的末尾
-(void)truncateFileAtOffset:offset 讲文件的长度设置为offset字节
-(void)closeFile 关闭文件
备注:
- 方法fileHandleForWritingAtPath和fileHandleForUpdatingAtPath所指定的文件必须是已经存在的,否则返回nil,另外对于这两个方法中文件的偏移量都是为文件的开始。
- 方法readDataToEndOfFile每次从文件中读取最多UNIT_MAX字节的数据,这个量定义在
示例
#import <Foundation/Foundation.h>
int main(int argc, const charchar * argv[])
{
@autoreleasepool {
NSFileHandle *inFile,*outFile;
NSData *buffer;
NSString *fileContent = @"这些是文件内容,这些是文件内容,这些是文件内容,这些是文件内容,这些是文件内容";
NSFileManager *fm = [NSFileManager defaultManager];
//创建一个文件
[fm createFileAtPath:@"testFile.txt" contents:[fileContent dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
//创建一个需要写入的文件
[fm createFileAtPath:@"outFile.txt" contents:nil attributes:nil];
//读取文件
inFile = [NSFileHandle fileHandleForReadingAtPath:@"testFile.txt"];
//写入文件
outFile = [NSFileHandle fileHandleForWritingAtPath:@"outFile.txt"];
if(inFile!=nil){
//读取文件内容
buffer = [inFile readDataToEndOfFile];
//将文件的字节设置为0,因为他可能包含数据
[outFile truncateFileAtOffset:0];
//将读取的内容内容写到outFile.txt中
[outFile writeData:buffer];
//关闭输出
[outFile closeFile];
//验证outFile内容
NSLog(@"%@",[NSString stringWithContentsOfFile:@"outFile.txt" encoding:NSUTF8StringEncoding error:NULL]);
//创建一个新的文件用来循环写入
[fm createFileAtPath:@"outFile2.txt" contents:nil attributes:nil];
//打开一个新的输出
outFile = [NSFileHandle fileHandleForWritingAtPath:@"outFile2.txt"];
//设置一个循环写入10条数据,每条数据都再后面添加上而不是覆盖
for (int i = 0; i<10; i++) {
//将偏移量设置为文件的末尾
[outFile seekToEndOfFile];
//写入数据
[outFile writeData:buffer];
}
//验证内容
NSLog(@"outFile2:%@",[NSString stringWithContentsOfFile:@"outFile2.txt" encoding:NSUTF8StringEncoding error:NULL]);
//关闭所有
[outFile closeFile];
[inFile closeFile];
}
}
return 0;
}
复杂对象的读写(I/O)
- 复杂对象指的是在Foundation框架内不存在的数据类,如自定以的Person类,像这种自定义的类是无法在程序内部通过writeToFile:这个方法写入到文件内
- 既然复杂对象无法使用内部方法进行数据持久化,那么 只能通过将复杂对象转换成NSData,然后在通过上面的方法写入文件,而这种转换的步骤就被称为归档,从文件中读取NSData数据,将NSData转换为复杂对象,这个步骤就是反归档
记住
- 复杂对象写入文件的过程(复杂对象->归档->NSData->writeToFile)
- 从文件中读取出复杂对象过程(读取文件->NSData->反归档->复杂对象
实现
-
首先,复杂对象所属的类要遵守<NSCoding>
@interface Person:NSObject**<NSCoding> ** @property(nonatomic,copy) NSString *name @property(nonatomic,assign) integer age; @end
-
其次,实现协议中的两个方法:
- (void)encodeWithCoder:(NSCoder *)aCoder; 序列化
- (id)initWithCoder:(NSCoder *)aDecoder; 反序列化
// 对person对象进行归档时,此方法执行。
// 对person中想要进行归档的所有属性,进行序列化操作。
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
}
// 对person对象进行反归档时,该方法执行。
// 创建一个新的person对象,所有属性都是通过反序列化得到的。
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
// 准备一个NSMutableData, 用于保存归档后的对象
NSMutableData *data = [NSMutableData data];
// 创建归档工具
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingMutableData:data];
// 归档
[archiver encodeObject:p] forKey:@"p1"];
// 结束
[archiver finishEncoding];
// 拼音写入沙盒路径
NSString *caches = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSString *filePath = [caches stringByAppendingPathComPonent:@"person"];
// 写入沙盒
[data writeToFile:filePath atomically:YES];
// 反归档
// 从filePath文件路径读取
NSData *data = [NSData dataWithContentsOfFile:filePath];
// 反归档工具
NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
// 反归档成对象
Person *p2 = [unArchiver decodeObjectForKey:@"p1"];
// 反归档结束
[unArchiver finshDeoding];