一. iOS沙盒机制
1. 文件操作的使用场景
- 数据持久化
- 减轻内存负担
- 分离数据源——如1-10分别对应不同的天气术语,分开存储
- 与文件,资源交互——.jpg .wav .avi
2. iOS沙盒机制
什么是沙盒
每个应用都有一个独立的存储空间,也就是文件夹,这个独立的存储空间叫做沙盒。-
应用沙盒的位置
-
沙盒的目录结构
-
如何快速的打开沙盒
二. 文件操作的相关使用
1. 主要文件夹路径获取
//
// MCFileManager.h
// FileOperationDemo
//
// Created by 李姝谊 on 2018/9/27.
// Copyright © 2018年 李姝谊. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface MCFileManager : NSObject
// 获取沙盒根目录
+ (NSString *)homeDirectory;
// 获取Documents目录
+ (NSString *)documentsDirectory;
// 获取Library目录
+ (NSString *)libraryDirectory;
// 获取Cache目录
+ (NSString *)cacheDirectory;
// 获取tmp目录
+ (NSString *)tmpDirectory;
@end
//
// MCFileManager.m
// FileOperationDemo
#import "MCFileManager.h"
@implementation MCFileManager
// 获取沙盒根目录
+ (NSString *)homeDirectory {
return NSHomeDirectory();
}
// 获取Documents目录
+ (NSString *)documentsDirectory {
/*
获取Documents目录
@param NSDocumentDirectory 要搜索的目录
@param NSUserDomainMask 要搜索的域,在iOS中固定填写
@param YES 是否展开波浪号,在iOS中固定填写
@return Documents目录路径
*/
NSString *documentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
return documentsDir;
}
// 获取Library目录
+ (NSString *)libraryDirectory {
/*
获取Library目录
@param NSLibraryDirectory 要搜索的目录
@param NSUserDomainMask 要搜索的域
@param YES 是否展开波浪号
@return Library目录路径
*/
NSString *libraryDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
return libraryDir;
}
// 获取Cache目录
+ (NSString *)cacheDirectory {
/*
获取Cache目录
@param NSCachesDirectory 要搜索的目录
@param NSUserDomainMask 要搜索的域
@param YES 是否展开波浪号
@return Cache目录路径
*/
NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
return cacheDir;
}
// 获取tmp目录
+ (NSString *)tmpDirectory {
return NSTemporaryDirectory();
}
@end
//
// ViewController.m
// FileOperationDemo
#import "ViewController.h"
#import "MCFileManager.h"
@interface ViewController ()
- (IBAction)printDirectory:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)printDirectory:(id)sender {
//打印主要路径
NSString *home = [MCFileManager homeDirectory];
NSLog(@"沙盒根目录:%@",home);
NSString *library = [MCFileManager libraryDirectory];
NSLog(@"Library目录:%@",library);
NSString *cache = [MCFileManager cacheDirectory];
NSLog(@"Cache目录:%@",cache);
NSString *tmp = [MCFileManager tmpDirectory];
NSLog(@"tmp目录:%@",tmp);
}
@end
2. 文件路径字符串的操作
//
// ViewController.m
// FileOperationDemo
#import "ViewController.h"
#import "MCFileManager.h"
@interface ViewController ()
- (IBAction)editPath:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)printDirectory:(id)sender {
//打印主要路径
NSString *home = [MCFileManager homeDirectory];
NSLog(@"沙盒根目录:%@",home);
NSString *library = [MCFileManager libraryDirectory];
NSLog(@"Library目录:%@",library);
NSString *cache = [MCFileManager cacheDirectory];
NSLog(@"Cache目录:%@",cache);
NSString *tmp = [MCFileManager tmpDirectory];
NSLog(@"tmp目录:%@",tmp);
}
- (IBAction)editPath:(id)sender {
//路径字符串的拼接和分离
NSString *cache = [MCFileManager cacheDirectory];
NSLog(@"Cache目录:%@",cache);
//追加路径
NSString *newDir = [cache stringByAppendingPathComponent:@"newDir"];
NSLog(@"新的路径:%@",newDir);
//获取某一个路径的父路径
NSString *fatherDir = [newDir stringByDeletingLastPathComponent];
NSLog(@"新路径的父路径:%@",fatherDir);
//创建新的文件路径
NSString *newFile = [cache stringByAppendingPathComponent:@"newFile"];
NSLog(@"新的文件:%@",newFile);
//增加扩展名
newFile = [newFile stringByAppendingPathExtension:@"txt"];
NSLog(@"追加了扩展名:%@",newFile);
//删除扩展名
newFile = [newFile stringByDeletingPathExtension];
NSLog(@"删除了扩展名:%@",newFile);
//拆分路径
NSArray *pathComponentsArray = [cache pathComponents];
NSLog(@"Cache目录拆分:%@",pathComponentsArray);
//获取路径最后一个Component
NSString *lastComponent = [cache lastPathComponent];
NSLog(@"最后一个Component:%@",lastComponent);
}
@end
3. 文件&文件夹存在性操作
//
// MCFileManager.h
// FileOperationDemo
#import <Foundation/Foundation.h>
@interface MCFileManager : NSObject
// 创建文件夹
+ (BOOL)createDirectoryInPath:(NSString *)path directoryName:(NSString *)name;
// 创建文件
+ (BOOL)createFileInPath:(NSString *)path fileName:(NSString *)fileName;
// 查询文件/文件夹是否存在
+ (BOOL)fileExistInPath:(NSString *)path isDirectory:(BOOL)isDirectory;
@end
//
// MCFileManager.m
// FileOperationDemo
#import "MCFileManager.h"
@implementation MCFileManager
/**
创建文件夹
@param path 要创建文件夹的上级路径
@param name 要创建文件夹的名称
@return 是否创建成功
*/
+ (BOOL)createDirectoryInPath:(NSString *)path directoryName:(NSString *)name {
NSFileManager *fileManager = [NSFileManager defaultManager];
//新的文件夹路径
NSString *newDir = [path stringByAppendingPathComponent:name];
//创建目录
//path 要创建的文件夹的路径
//withIntermediateDirectories 如果缺少中间路径是否连同中间路径一起创建
//attributes 传入nil表示使用默认属性
//error 传入nil表示不获取失败原因
BOOL result = [fileManager createDirectoryAtPath:newDir withIntermediateDirectories:YES attributes:nil error:nil];
return result;
}
/**
创建文件
@param path 要创建文件的上级路径
@param fileName 要创建的文件名
@return 是否创建成功
*/
+ (BOOL)createFileInPath:(NSString *)path fileName:(NSString *)fileName {
//获取文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
//新文件的完整路径
NSString *newFilePath = [path stringByAppendingPathComponent:@"newFilePath"];
//createFileAtPath 要创建文件的完整路径
//contents 文件内容,传入nil表示不添加任何内容
//attributes 传入nil表示使用默认属性
BOOL result = [fileManager createFileAtPath:newFilePath contents:nil attributes:nil];
return result;
}
/**
查询文件/文件夹是否存在
@param path 查询的路径
@param isDirectory 如果路径存在,这个路径是一个文件还是文件夹(输出参数
@return 返回文件/文件夹是否存在
*/
+ (BOOL)fileExistInPath:(NSString *)path isDirectory:(BOOL)isDirectory {
//获取文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
/*
查询文件/文件夹是否存在
@param fileExistsAtPath 要查询的路径
@param isDirectory 如果路径存在,这个路径是一个文件还是文件夹(输出参数)
*/
BOOL exist = [fileManager fileExistsAtPath:path isDirectory:isDirectory];
return exist;//结果为true,则文件或文件夹存在
}
@end
//
// ViewController.m
// FileOperationDemo
#import "ViewController.h"
#import "MCFileManager.h"
@interface ViewController ()
- (IBAction)pathExist:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)pathExist:(id)sender {
//文件存在性操作
//创建文件夹
NSString *directoryName = @"MyDirectory";
NSString *cachePath = [MCFileManager cacheDirectory];
BOOL createResult = [MCFileManager createDirectoryInPath:cachePath directoryName:directoryName];
if (createResult) {
NSLog(@"创建文件夹%@成功",directoryName);
} else {
NSLog(@"创建文件夹%@失败",directoryName);
}
//创建文件
NSString *fileName = @"myFile.txt";
createResult = [MCFileManager createFileInPath:cachePath fileName:fileName];
if (createResult) {
NSLog(@"创建文件%@成功",fileName);
} else {
NSLog(@"创建文件%@失败",fileName);
}
//查询文件是否存在
BOOL isDirectory;
NSString *filePath = [cachePath stringByAppendingPathComponent:fileName];
BOOL fileExist = [MCFileManager fileExistInPath:filePath isDirectory:&isDirectory];
NSLog(@"文件是否存在:%@ 是否是文件夹:%@",fileExist?@"是":@"否",isDirectory?@"是":@"否");
}
@end
4. 简单文件读写
//
// MCFileManager.h
// FileOperationDemo
#import <Foundation/Foundation.h>
@interface MCFileManager : NSObject
// 读取文件
+ (NSString *)readFileFromPath:(NSString *)path;
// 写入字符串到文件(覆盖写)
+ (BOOL)writeString:(NSString *)content toPath:(NSString *)path;
@end
//
// MCFileManager.m
// FileOperationDemo
#import "MCFileManager.h"
@implementation MCFileManager
/**
读取文件
@param path 文件路径
@return 文件内容
*/
+ (NSString *)readFileFromPath:(NSString *)path {
/*
stringWithContentsOfFile 文件路径
encoding 文件的编码格式
error 输出参数,返回错误原因
返回值 读取到的文件内容字符串
*/
NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
return content;
}
/**
写入字符串到文件(覆盖写)
@param content 要写入的内容
@param path 要写入的文件的路径
@return 是否写入成功
*/
+ (BOOL)writeString:(NSString *)content toPath:(NSString *)path {
//atomically 是否安全读写,如果传入YES,写入文件时,系统会创建一个临时文件,将写入内容写入临时文件,写入完毕后,将临时文件重命名为我们想要写入的文件,如果传入No,则直接写入文件中
BOOL result = [content writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
return result;
}
@end
//
// ViewController.m
// FileOperationDemo
#import "ViewController.h"
#import "MCFileManager.h"
@interface ViewController ()
- (IBAction)fileSimpleReadWrite:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)fileSimpleReadWrite:(id)sender {
NSString *fileName = @"myFile.txt";
NSString *filePath = [[MCFileManager cacheDirectory]stringByAppendingPathComponent:fileName];
NSString *content = @"Hello World";
//写入文件
if ([MCFileManager writeString:content toPath:filePath]) {
NSLog(@"写入文件%@成功",fileName);
} else {
NSLog(@"写入文件%@失败",fileName);
}
//读取文件
NSString *readContent = [MCFileManager readFileFromPath:filePath];
if (readContent.length > 0) {
//读取到内容
NSLog(@"读取%@文件内容:%@",fileName,readContent);
} else {
NSLog(@"读取文件%@失败",fileName);
}
}
@end
5. 文件的高级读写
//
// MCFileManager.h
// FileOperationDemo
#import <Foundation/Foundation.h>
@interface MCFileManager : NSObject
// 读取文件(使用NSFileHandle)
+ (NSString *)readFileUsingFileHandleFromPath:(NSString *)path;
// 覆盖写文件(使用NSFileHandle)
+ (BOOL)writeStringUsingFileHandle:(NSString *)content toPath:(NSString *)path;
// 追加文件(使用NSFileHandle)
+ (BOOL)appendStringUsingFileHandle:(NSString *)content toPath:(NSString *)path;
@end
//
// MCFileManager.m
// FileOperationDemo
#import "MCFileManager.h"
@implementation MCFileManager
/**
读取文件(使用NSFileHandle)
@param path 文件的路径
@return 文件的内容字符串
*/
+ (NSString *)readFileUsingFileHandleFromPath:(NSString *)path {
NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path];
if (file) {
NSData *content = [file readDataToEndOfFile];
[file closeFile];
NSString *contentString = [[NSString alloc]initWithData:content encoding:NSUTF8StringEncoding];
return contentString;
} else {
return nil;
}
}
/**
覆盖写文件(使用NSFileHandle)
@param content 要写入的内容
@param path 写入的文件路径
@return 写入是否成功
*/
+ (BOOL)writeStringUsingFileHandle:(NSString *)content toPath:(NSString *)path {
//[self fileExistInPath:path isDirectory:nil]这个是上文自己创建的方法
if (![self fileExistInPath:path isDirectory:nil]) {
//如果文件不存在,创建这个文件
//createFileAtPath:path contents:nil attributes:nil 这个是上文自己创建的方法
BOOL result = [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
if (result == NO) {
return NO;
}
}
//获取FileHandle实例,对文件进行操作
NSFileHandle *file = [NSFileHandle fileHandleForWritingAtPath:path];
if (file) {
NSData *dataContent = [content dataUsingEncoding:NSUTF8StringEncoding];
[file truncateFileAtOffset:0];//将偏移量为0后面的内容清空
[file writeData:dataContent];
[file closeFile];
return YES;
} else {
return NO;
}
}
/**
追加文件(使用NSFileHandle)
@param content 要写入的内容
@param path 写入的文件路径
@return 写入是否成功
*/
+ (BOOL)appendStringUsingFileHandle:(NSString *)content toPath:(NSString *)path {
if (![self fileExistInPath:path isDirectory:nil]) {
//如果文件不存在,创建这个文件
BOOL result = [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
if (result == NO) {
return NO;
}
}
//获取FileHandle实例,对文件进行操作
NSFileHandle *file = [NSFileHandle fileHandleForWritingAtPath:path];
if (file) {
NSData *dataContent = [content dataUsingEncoding:NSUTF8StringEncoding];
[file seekToEndOfFile];//将文件操作的指针指向文件结尾
[file writeData:dataContent];
[file closeFile];
return YES;
} else {
return NO;
}
}
@end
//
// ViewController.m
// FileOperationDemo
#import "ViewController.h"
#import "MCFileManager.h"
@interface ViewController ()
- (IBAction)fileAdvancedReadWrite:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)fileAdvancedReadWrite:(id)sender {
NSString *fileName = @"myFile.txt";
NSString *filePath = [[MCFileManager cacheDirectory]stringByAppendingPathComponent:fileName];
NSString *content = @"Hello World";
if([MCFileManager writeStringUsingFileHandle:content toPath:filePath]) {
NSLog(@"写入文件%@成功",fileName);
} else {
NSLog(@"写入文件%@失败",fileName);
}
NSString *fileContent = [MCFileManager readFileUsingFileHandleFromPath:filePath];
NSLog(@"读取%@文件内容:%@",fileName,fileContent);
NSString *appendContent = @"你好 世界";
if ([MCFileManager appendStringUsingFileHandle:appendContent toPath:filePath]) {
NSLog(@"追加写文件成功");
} else {
NSLog(@"追加写文件失败");
}
fileContent = [MCFileManager readFileUsingFileHandleFromPath:filePath];
NSLog(@"读取%@文件内容:%@",fileName,fileContent);
}
@end
6. 字典到文件的读写
//
// MCFileManager.h
// FileOperationDemo
#import <Foundation/Foundation.h>
@interface MCFileManager : NSObject
// 写入字典到plist文件
+ (BOOL)saveDictionary:(NSDictionary *)dict isPlistFileOfPath:(NSString *)path;
// 从plist文件中读取字典
+ (NSDictionary *)dictionaryInPlistFileOfPath:(NSString *)path;
@end
//
// MCFileManager.m
// FileOperationDemo
#import "MCFileManager.h"
@implementation MCFileManager
/**
写入字典到plist文件
@param dict 要写入的字典
@param path 要写入的路径
@return 是否写入成功
*/
+ (BOOL)saveDictionary:(NSDictionary *)dict isPlistFileOfPath:(NSString *)path {
//判断dict是否是有效字典
if (dict && [dict isKindOfClass:[NSDictionary class]]) {
//dict有效
return [dict writeToFile:path atomically:YES];
} else {
return NO;
}
}
/**
从plist文件中读取字典
@param path 文件的路径
@return 读取到的字典
*/
+ (NSDictionary *)dictionaryInPlistFileOfPath:(NSString *)path {
//判断文件是否存在,调用上文自己写的方法
if ([self fileExistInPath:path isDirectory:nil]) {
//文件存在
NSDictionary *dict = [[NSDictionary alloc]initWithContentsOfFile:path];
if (dict && [dict isKindOfClass:[NSDictionary class]]) {
//dict有效
return dict;
}else {
return nil;
}
} else {
return nil;
}
}
@end
//
// ViewController.m
// FileOperationDemo
#import "ViewController.h"
#import "MCFileManager.h"
@interface ViewController ()
- (IBAction)convertDictAndFile:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)convertDictAndFile:(id)sender {
NSString *fileName = @"myKeyValue.plist";
NSString *filePath = [[MCFileManager cacheDirectory]stringByAppendingPathComponent:fileName];
NSDictionary *dict = @{@"key1":@"value1",@"key2":@"value2"};
if ([MCFileManager saveDictionary:dict isPlistFileOfPath:filePath]) {
NSLog(@"写入文件%@成功",fileName);
} else {
NSLog(@"写入文件%@失败",fileName);
}
NSDictionary *dictToRead = [MCFileManager dictionaryInPlistFileOfPath:filePath];
NSLog(@"读取%@文件内容:%@",fileName,dictToRead);
}
@end
7. Bundle资源文件读取
- (IBAction)findBundleFilePath:(id)sender {
NSString *fileName = @"myBundleFile.txt";
//查找文件路径
NSString *filePath = [[NSBundle mainBundle]pathForResource:fileName ofType:nil];
NSLog(@"%@文件的路径:%@",fileName,filePath);
}
8. 递归打印沙盒所有路径
//
// MCFileManager.h
// FileOperationDemo
#import <Foundation/Foundation.h>
@interface MCFileManager : NSObject
// 递归打印沙盒下的所有的文件和文件夹
+ (void)printHierachyOfSandBox;
@end
//
// MCFileManager.m
// FileOperationDemo
#import "MCFileManager.h"
@implementation MCFileManager
/**
列出某个路径下所有的文件或文件夹
@param path 指定的路径
@return 这个路径下所有的文件或文件夹
*/
+ (NSArray *)listForPath:(NSString *)path {
return [[NSFileManager defaultManager]contentsOfDirectoryAtPath:path error:nil];
}
/**
递归打印某个路径下的所有的文件和文件夹
@param path 指定的路径
@param level 打印时缩进的等级
*/
+ (void)recursionPrintListOfPath:(NSString *)path forLevel:(NSInteger)level {
NSArray *fileList = [self listForPath:path];
for (NSString *fileName in fileList) {
//确定打印的缩进
NSString *indent = @"";//缩进字符串
for (int i = 0; i < level; i++) {
indent = [indent stringByAppendingString:@"..."];
}
//打印这个文件/文件夹名
NSLog(@"%@/%@",indent,fileName);
NSString *filePath = [path stringByAppendingPathComponent:fileName];
BOOL isDirectory = false;
//判断路径是一个文件还是文件夹
[self fileExistInPath:filePath isDirectory:&isDirectory];
if (isDirectory) {
//如果是一个文件夹,则递归打印这个文件夹下所有的文件和文件夹
[self recursionPrintListOfPath:filePath forLevel:level+1];
}
}
}
/**
递归打印沙盒下的所有的文件和文件夹
*/
+ (void)printHierachyOfSandBox {
[self recursionPrintListOfPath:[self homeDirectory] forLevel:0];
}
@end
//
// ViewController.m
// FileOperationDemo
#import "ViewController.h"
#import "MCFileManager.h"
@interface ViewController ()
- (IBAction)printSandBox:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)printSandBox:(id)sender {
[MCFileManager printHierachyOfSandBox];
}
@end
9. 应用日志文件化
//
// MCFileManager.h
// FileOperationDemo
#import <Foundation/Foundation.h>
#define PLog(format, ...) [MCFileManager logWithFormat:format, ## __VA_ARGS__]// ## __VA_ARGS__表示可变参数
@interface MCFileManager : NSObject
//应用日志文件化
+ (void)logWithFormat:(NSString*)format, ...;
@end
//
// MCFileManager.m
// FileOperationDemo
#import "MCFileManager.h"
@implementation MCFileManager
/**
* 应用日志文件化 格式化log到文件中
*
* @param format log字符串的格式,方法有可变参数,用法与NSLog类似
*/
+ (void)logWithFormat:(NSString*)format, ...{
va_list paramList;
va_start(paramList, format);//初始化参数列表
NSString* logString = [[NSString alloc]initWithFormat:format arguments:paramList];//生成格式化字符串
NSString* logToStore = [logString stringByAppendingString:@"\n"];
va_end(paramList);//释放paramList内存
//生成log存储的文件路径
NSString* logPath = [[self cacheDirectory] stringByAppendingPathComponent:@"log.txt"];
//存储log,追加内容到log文件中
BOOL writeResult = [self appendStringUsingFileHandle:logToStore toPath:logPath];
if (writeResult) {
//写入Log成功
NSLog(@"%@",logString);
}else{
//写入log失败
NSLog(@"写入log失败:%@",logString);
}
}
@end
//
// ViewController.m
// FileOperationDemo
#import "ViewController.h"
#import "MCFileManager.h"
@interface ViewController ()
- (IBAction)logToFile:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)logToFile:(id)sender {
// [MCFileManager logWithFormat:@"%@,%@",@"hello",@"你好"];
PLog(@"%@,%@",@"HELLO",@"你好2");
}
@end