日常使用苹果的APP的时候,我们保存的数据大都保存在哪里呢?
通常情况下,我们的数据多数保存在一个叫沙盒的结构中。所以了解苹果的沙盒存储机制是了解苹果数据存储的第一道门。
一、概述:
- 介绍:应用沙盒机制:每个iOS应用都有自己的应用沙盒(文件系统目录),与其他文件系统隔离。每个应用必须在自己的沙盒里运行,其他应用不能访问该沙盒。
- 特点:
- 每个应用程序的活动范围都限定在自己的沙盒里。
- 不能随意跨越自己的沙盒去访问别的应用程序沙盒中的内容。
- 在访问别人沙盒内的数据时需要访问权限。
二、沙盒结构介绍:
- 获取 软件的沙盒路径:
- 通过
NSHomeDirectory()
获取沙盒路径并输出:
NSLog(@"%@",NSHomeDirectory());
- 通过
NSSearchPathForDirectoriesInDomains()
方法去查找路径:
NSSearchPathForDirectoriesInDomains的参数说明:
directory :表示需要查找的是哪一个文件夹,是一个枚举
domainMask:搜索范围,是一个枚举类型;关于domainMask 看:NSSearchPathDomainMask详解
expandTilde:是否扩展路径,YES->获取完整路径,一般为YES
return:返回值为数组,这个数组中只有一个NSString类型元素,一般这个元素保存的就是查找的路径的唯一路径,所以直接取第一个就行了
- 通过
一般的沙盒的的根目录有三个文件夹,分别是:Documents
、Library
和tmp
- Documents/:
Documents一般用来保存APP中需要持久保存的文件和数据
,例如游戏进度,绘图软件的绘图等,当iTunes 连接的时候会去备份和恢复Documents文件夹数据
⚠️注意:在此目录下不要保存从网络上下载的文件,否则app无法上架!
获取 Documents/ 文件的路径:
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- Library/:
Library目录下有两个子目录:Caches 和 Preferences
获取 Library/ 的路径:
NSString *path = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES).lastObject;
- Library/Caches:
顾名思义,用来保存数据中的一些缓存的持久化数据
,这些数据一般是体积较大,但并不是绝对需要的数据(多为网络请求的数据,如图片和视频等),这些数据需要用户自己去管理删除,当iTunes 连接的时候不会去备份和恢复数据
获取 Library/Caches 路径
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
- Library/Preferences:
Preferences翻译过来就是偏好、偏爱的意思,所以多用来保存软件一些偏好设置(setting)
,当iTunes 连接的时候会去备份和恢复 Library/Preferences文件夹数据
获取Library/Preferences的路径:
NSString *path = NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSUserDomainMask, YES).lastObject;
- tmp/:
此目录保存应用程序运行时所需的临时数据
,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份 tmp 目录
获取 tmp/ 文件夹路径:
NSString *path = NSTemporaryDirectory();
三、文件操作
- 创建文件夹/目录
通过 createDirectoryAtPath 方法实现:
- (BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(nullable NSDictionary *)attributes error:(NSError **)error;
参数说明:
path:文件夹/目录的路径
withIntermediateDirectories:中间目录,如果为createIntermediates传递'NO',则在进行此调用时目录不能存在。为“createIntermediates”传递“YES”将创建任何必要的中间目录。如果创建了“path”中指定的所有目录并设置了属性,则此方法返回YES。,一般返回YES
attributes:目录是用传递给“attributes”的字典指定的属性创建的。如果没有提供字典,则根据进程的umask创建目录。具体设置查看文章
(Objective-C创建目录接口)[https://blog.csdn.net/wanganqi19920813/article/details/8849706]
error:如果提供了错误参数,则会通过引用返回可呈现的NSError
return:如果在操作的任何阶段发生故障,则此方法返回NO
-(BOOL)createDir:(NSString *)fileName{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString * path = [NSString stringWithFormat:@"%@/%@",documentsDirectory,fileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDir;
if (![fileManager fileExistsAtPath:path isDirectory:&isDir]) {//先判断目录是否存在,不存在才创建
BOOL res=[fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
return res;
} else return NO;
- 创建文件
通过 createFileAtPath:方法实现
- (BOOL)createFileAtPath:(NSString *)path contents:(nullable NSData *)data attributes:(nullable NSDictionary *)attr
参数介绍:
path:用来指定要创建的文件
data:用来指定文件中的数据
attr:用来指定字典,一般设置为nil
return:返回创建的结果
当(NSData *)data和(NSDictionary *)attr都设置为nil时,创建出来的文件就是一个空文件。
-(BOOL)createFile:(NSString *)path{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *testPath = [path stringByAppendingPathComponent:@"test.c"];//在传入的路径下创建test.c文件
//通过data创建数据
NSData *data=[@"Hello world" dataUsingEncoding:NSUTF8StringEncoding];
BOOL res = [fileManager createFileAtPath:testPath contents:data attributes:nil];
return res;
}
- 写数据到文件
通过 writeToFile: 方法实现
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error
参数说明:
path:存储的文件夹路径
atomically:如果为YES则保证文件的写入原子性,就是说会先创建一个临时文件,直到文件内容写入成功再导入到目标文件里,如果为NO,则直接写入目标文件里
encoding:格式
error:错误信息
return:写入是否正确
- 读数据
通过 stringWithContentsOfFile: 或者 initWithContentsOfFile: 方法实现
参数和写入的差不多
-(void)readFile:(NSString *)path{
//方法1:
NSData * data = [NSData dataWithContentsOfFile:path];
NSString * content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
//方法2:
NSString * content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSLog(@"文件读取成功: %@",content);
}
- 查看是否有相关文件
通过方法 isExecutableFileAtPath:
- (BOOL)isExecutableFileAtPath:(NSString *)path
- 获取文件的属性:
-(void)fileAttriutes:(NSString *)path{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:path error:nil];
NSArray *keys;
id key, value;
keys = [fileAttributes allKeys];
int count = [keys count];
for (int i = 0; i < count; i++)
{
key = [keys objectAtIndex: i]; //获取文件名
value = [fileAttributes objectForKey: key]; //获取文件属性
}
}
- 根据路径删除文件
通过方法 removeItemAtPath:
-(BOOL)deleteFileByPath:(NSString *)path{
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL res=[fileManager removeItemAtPath:path error:nil];
return res;
}
- 根据文件名删除文件
- (BOOL)deleteFileByName:(NSString *)name{
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:[self getLocalFilePath:fileName] error:nil];//getLocalFilePath方法在下面
}
- 复制文件
通过 copyItemAtPath: 方法实现
+(BOOL)copyFile:(NSString *)path topath:(NSString *)topath
{
BOOL result = NO;
NSError * error = nil;
result = [[NSFileManager defaultManager]copyItemAtPath:path toPath:topath error:&error ];
if (error){
NSLog(@"copy失败:%@",[error localizedDescription]);
}
return result;
}
- 根据文件名获取文件路径
- 资源文件
+(NSString *)getResourcesFile:(NSString *)fileName
{
return [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
}
- 普通文件
+(NSString *)getLocalFilePath:(NSString *) fileName
{
NSString * path = [NSHomeDirectory() stringByAppendingPathComponent:@"/Documents"]
return [NSString stringWithFormat:@"%@/%@",path,fileName];
}
- 根据文件路径获取文件名称
+(NSString *)getFileNameByPath:(NSString *)filepath
{
NSArray *array=[filepath componentsSeparatedByString:@"/"];
if (array.count==0) return filepath;
return [array objectAtIndex:array.count-1];
}
- 根据路径获取该路径下所有目录
+(NSArray *)getAllFileByName:(NSString *)path
{
NSFileManager *defaultManager = [NSFileManager defaultManager];
NSArray *array = [defaultManager contentsOfDirectoryAtPath:path error:nil];
return array;
}
- 根据路径获取文件目录下所有文件
+(NSArray *)getAllFloderByName:(NSString *)path
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray * fileAndFloderArr = [self getAllFileByName:path];
NSMutableArray *dirArray = [[NSMutableArray alloc] init];
BOOL isDir = NO;
//在上面那段程序中获得的fileList中列出文件夹名
for (NSString * file in fileAndFloderArr){
NSString *paths = [path stringByAppendingPathComponent:file];
[fileManager fileExistsAtPath:paths isDirectory:(&isDir)];
if (isDir) {
[dirArray addObject:file];
}
isDir = NO;
}
return dirArray;
}
14.获取文件及目录的大小
+(float)sizeOfDirectory:(NSString *)dir{
NSDirectoryEnumerator *direnum = [[NSFileManager defaultManager] enumeratorAtPath:dir];
NSString *pname;
int64_t s=0;
while (pname = [direnum nextObject]){
//NSLog(@"pname %@",pname);
NSDictionary *currentdict=[direnum fileAttributes];
NSString *filesize=[NSString stringWithFormat:@"%@",[currentdict objectForKey:NSFileSize]];
NSString *filetype=[currentdict objectForKey:NSFileType];
if([filetype isEqualToString:NSFileTypeDirectory]) continue;
s=s+[filesize longLongValue];
}
return s*1.0;
}
- 重命名文件或者目录
+(BOOL)renameFileName:(NSString *)oldName toNewName:(NSString *)newName
{
BOOL result = NO;
NSError * error = nil;
result = [[NSFileManager defaultManager] moveItemAtPath:[kDSRoot stringByAppendingPathComponent:oldName] toPath:[kDSRoot stringByAppendingPathComponent:newName] error:&error];
if (error){
NSLog(@"重命名失败:%@",[error localizedDescription]);
}
return result;
}
- 读取文件
+(NSData *)readFileContent:(NSString *)filePath{
return [[NSFileManager defaultManager] contentsAtPath:filePath];
}
- 保存文件
+(BOOL)saveToDirectory:(NSString *)path data:(NSData *)data name:(NSString *)newName
{
NSString * resultPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@",newName]];
return [[NSFileManager defaultManager] createFileAtPath:resultPath contents:data attributes:nil];
}
沙盒的介绍就到这里,如果喜欢不妨点个赞,如有错误或者疑问欢迎评论区留言,一起加油⛽️
参考文章:
iOS 开发之沙盒机制
iOS之NSFilemanager文件管理(沙盒)