iOS 关于文件操作 NSFileManager

[TOC]
相关知识
--

沙盒机制

每一个iOS应用程序都会为自己创建一个文件系统目录,这个独立、封闭、安全的空间叫做沙盒。沙盒就是一种安全体系,它规定了应用程序只能在自己的文件系统目录内访问文件,不可以访问其他应用沙盒内的内容。所有的非代码文件都保存在这个地方。

沙盒根目录结构:Documents、Library、temp

沙盒目录

Documents

保存应用运行时生成的需要持久化的数据,iTunes备份和恢复的时候会包括此目录,所以苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下。

Library

  • Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出后删除 。一般存放体积比较大,不是特别重要的资源。
  • Preferences:保存APP的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息,iTunes会自动备份该目录。注意:通过NSUserDefaults类来读取和设置。

tmp

保存应用运行时所需的临时数据,这个可以放一些当APP退出后不再需要的文件。应用没有运行时,系统也有可能会清除该目录下的文件,iTunes不会同步该目录。iPhone重启时,该目录下的文件会被删除。

如何查看该目录?

XCode->Window->Devices->真机->Installed Apps->应用->ShowContainer

沙盒目录

也可以点击DownloadContainer下载该沙盒文件查看内容

沙盒内容

获取相关目录

// 获取Document目录
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
 
// 获取Library目录
NSString *LibraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
 
// 获取Caches目录
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
 
// 获取Preferences目录 通常情况下,Preferences有系统维护,所以我们很少去操作它。
NSString *preferPath = [LibraryPath stringByAppendingPathComponent:@"Preferences"];

// 获取tmp目录
NSString *tmpPath = NSTemporaryDirectory();

[toc]
相关文件操作
--

  • 创建文件夹
+(BOOL)creatDir:(NSString *)path{
    if (path.length==0) {
        return NO;
    }
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isSuccess = YES;
    BOOL isExist = [fileManager fileExistsAtPath:path];
    if (isExist==NO) {
        NSError *error;
        if (![fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]) {
            isSuccess = NO;
            NSLog(@"creat Directory Failed:%@",[error localizedDescription]);
        }
    }
    return isSuccess;
}
  • 创建文件
+(BOOL)creatFile:(NSString*)filePath{
    if (filePath.length==0) {
        return NO;
    }
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:filePath]) {
        return YES;
    }
    NSError *error;
    NSString *dirPath = [filePath stringByDeletingLastPathComponent];
    BOOL isSuccess = [fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:&error];
    if (error) {
        NSLog(@"creat File Failed:%@",[error localizedDescription]);
    }
    if (!isSuccess) {
        return isSuccess;
    }
    isSuccess = [fileManager createFileAtPath:filePath contents:nil attributes:nil];
    return isSuccess;
}
  • 写数据
+(BOOL)writeToFile:(NSString*)filePath contents:(NSData *)data{
    if (filePath.length==0) {
        return NO;
    }
    BOOL result = [self creatFile:filePath];
    if (result) {
        if ([data writeToFile:filePath atomically:YES]) {
            NSLog(@"write Success");
        }else{
            NSLog(@"write Failed");
        }
    }
    else{
        NSLog(@"write Failed");
    }
    return result;
}
  • 追加写数据
+(BOOL)appendData:(NSData*)data withPath:(NSString *)filePath{
    if (filePath.length==0) {
        return NO;
    }
    BOOL result = [self creatFile:filePath];
    if (result) {
        NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:filePath];
        [handle seekToEndOfFile];
        [handle writeData:data];
        [handle synchronizeFile];
        [handle closeFile];
    }
    else{
        NSLog(@"appendData Failed");
    }
    return result;
}
  • 读文件数据
+(NSData*)readFileData:(NSString *)path{
    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
    NSData *fileData = [handle readDataToEndOfFile];
    [handle closeFile];
    return fileData;
}
  • 获取文件夹下所有的文件列表
+(NSArray*)getFileList:(NSString*)path{
    if (path.length==0) {
        return nil;
    }
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *fileList = [fileManager contentsOfDirectoryAtPath:path error:&error];
    if (error) {
        NSLog(@"getFileList Failed:%@",[error localizedDescription]);
    }
    return fileList;
}
  • 获取文件夹下所有文件(深度遍历)
+(NSArray*)getAllFileList:(NSString*)path{
    if (path.length==0) {
        return nil;
    }
    NSArray *fileArray = [self getFileList:path];
    NSMutableArray *fileArrayNew = [NSMutableArray array];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    for (NSString *aPath in fileArray) {
        NSString * fullPath = [path stringByAppendingPathComponent:aPath];
        BOOL isDir = NO;
        if ([fileManager fileExistsAtPath:fullPath isDirectory:&isDir]) {
            if (isDir) {
                [fileArrayNew addObjectsFromArray:[self getAllFileList:fullPath]];
            }else{
                [fileArrayNew addObject:fullPath];
            }
        }
    }
    return fileArrayNew;
}
  • 移动文件
+(BOOL)moveFile:(NSString *)fromPath toPath:(NSString *)toPath toPathIsDir:(BOOL)dir{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:fromPath]) {
        NSLog(@"Error: fromPath Not Exist");
        return NO;
    }
    BOOL isDir = NO;
    BOOL isExist = [fileManager fileExistsAtPath:toPath isDirectory:&isDir];
    if (isExist) {
        if (isDir) {
            if ([self creatDir:toPath]) {
                NSString *fileName = fromPath.lastPathComponent;
                toPath = [toPath stringByAppendingPathComponent:fileName];
                return [self moveItemAtPath:fromPath toPath:toPath];
            }
        }else{
            [self removeFile:toPath];
            return [self moveItemAtPath:fromPath toPath:toPath];
        }
    }
    else{
        if (dir) {
            if ([self creatDir:toPath]) {
                NSString *fileName = fromPath.lastPathComponent;
                toPath = [toPath stringByAppendingPathComponent:fileName];
                return [self moveItemAtPath:fromPath toPath:toPath];
            }
        }else{
            return [self moveItemAtPath:fromPath toPath:toPath];
        }
    }
    return NO;
}
+(BOOL)moveItemAtPath:(NSString*)fromPath toPath:(NSString*)toPath{
    BOOL result = NO;
    NSError * error = nil;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    result = [fileManager moveItemAtPath:fromPath toPath:toPath error:&error];
    if (error){
        NSLog(@"moveFile Fileid:%@",[error localizedDescription]);
    }
    return result;
}
  • 删除文件
+(BOOL)removeFile:(NSString*)filePath{
    BOOL isSuccess = NO;
    NSError *error;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    isSuccess = [fileManager removeItemAtPath:filePath error:&error];
    if (error) {
        NSLog(@"removeFile Field:%@",[error localizedDescription]);
    }else{
        NSLog(@"removeFile Success");
    }
    return isSuccess;
}
  • 删除文件夹
+(BOOL)removeDir:(NSString*)path{
    return [self removeFile:path];
}
  • 删除某些后缀的文件
+(void)removeFileSuffixList:(NSArray<NSString*>*)suffixList filePath:(NSString*)path deep:(BOOL)deep{
    NSArray *fileArray = nil;
    if (deep) {  // 是否深度遍历
        fileArray = [self getAllFileList:path];
    }else{
        fileArray = [self getFileList:path];
        NSMutableArray *fileArrayTmp = [NSMutableArray array];
        for (NSString *fileName in fileArray) {
            NSString* allPath = [path stringByAppendingPathComponent:fileName];
            [fileArrayTmp addObject:allPath];
        }
        fileArray = fileArrayTmp;
    }
    for (NSString *aPath in fileArray) {
        for (NSString* suffix in suffixList) {
            if ([aPath hasSuffix:suffix]) {
                [self removeFile:aPath];
            }
        }
    }
}
  • 获取文件大小
+(long long)getFileSize:(NSString*)path{
    unsigned long long fileLength = 0;
    NSNumber *fileSize;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:path error:nil];
    if ((fileSize = [fileAttributes objectForKey:NSFileSize])) {
        fileLength = [fileSize unsignedLongLongValue]; //单位是 B
    }
    return fileLength;
}
  • 获取文件的信息(包含了上面文件大小)
+(NSDictionary*)getFileInfo:(NSString*)path{
    NSError *error;
    NSDictionary *reslut =  [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&error];
    if (error) {
        NSLog(@"getFileInfo Failed:%@",[error localizedDescription]);
    }
    return reslut;
}

[toc]

NSFileManager和NSFileHandle

1、NSFileManager(文件管理对象)

主要是对文件进行的操作(创建/删除/改名等)以及文件信息的获取。

方法 说明
@property (class, readonly, strong) NSFileManager *defaultManager 创建文件管理对象
-(BOOL)fileExistsAtPath:(NSString *)path isDirectory:(nullable BOOL *)isDirectory 判断某个路径是否存在,isDirectory是一个指针,表示该路径是否是目录
-(BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(nullable NSDictionary<NSString *, id> *)attributes error:(NSError **)error 创建一个目录
-(BOOL)createFileAtPath:(NSString *)path contents:(nullable NSData *)data attributes:(nullable NSDictionary<NSString *, id> *)attr 创建一个文件,可顺便写入data
-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile NSData类型的写入数据,读数据请自行查阅
-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error NSString、NSArray、NSDictionary的写入数据,读数据请自行查阅
-(nullable NSArray<NSString *> *)contentsOfDirectoryAtPath:(NSString *)path error:(NSError **)error 获取当前文件夹下的文件/目录
-(BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error 移动文件,可用来重命名
-(BOOL)copyItemAtURL:(NSURL *)srcURL toURL:(NSURL *)dstURL error:(NSError **)error 复制文件
-(BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error 删除文件
-(nullable NSDictionary<NSFileAttributeKey, id> *)attributesOfItemAtPath:(NSString *)path error:(NSError **)error 获取文件信息(文件大小、修改时间、所有者等)

</b>

2、NSFileHandle(文件连接器)

主要是对文件内容进行读取和写入操作

方法 说明
+(nullable instancetype)fileHandleForWritingAtPath:(NSString *)path 写的方式打开文件
+(nullable instancetype)fileHandleForReadingAtPath:(NSString *)path 读的方式打开文件
-(unsigned long long)seekToEndOfFile 跳到文件末尾
-(void)seekToFileOffset:(unsigned long long)offset 跳到指定偏移位置
-(void)truncateFileAtOffset:(unsigned long long)offset 将文件的长度设为offset字节
-(NSData *)readDataToEndOfFile 从当前字节读取到文件到末尾数据
-(NSData *)readDataOfLength:(NSUInteger)length 从当前字节读取到指定长度数据
-(void)synchronizeFile 同步文件,通常用在写入数据后
-(void)closeFile 关闭文件

[toc]

对象等复杂类型的读写操作

上述数据操作,支持的类型仅仅是NSString、NSArray、NSDictionary、NSData类型,这些都数据类型都支持了NSCoding协议,可以进行数据持久化。如果我们想存储如UIImage、自定义的对象等类型,我们都需要将其转换为NSData类型,如转换UIImage为NSData使用UIImagePNGRepresentation(image)等方法,而自定义对象类型则需要进行归档、反归档来进行存取操作

存:

对象->归档->NSData->文件写入

取:

文件读取->NSData->反归档->对象

自定义对象需要遵守NSCoding协议并实现

- (void)encodeWithCoder:(NSCoder *)aCoder;  //序列化 
- (id)initWithCoder:(NSCoder *)aDecoder;    //反序列化

两个方法


[toc]

参考地址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,121评论 29 470
  • 1、 沙盒概念基本介绍 iOS 应用程序只能在该 app 的文件系统中读取。这个默认的 app 文件系统就是我们说...
    Laughingg阅读 2,636评论 2 10
  • 目录 沙盒及其结构 Preference(偏好设置)-Plist 属性列表-Plist NSKeyedArchiv...
    Ryan___阅读 468评论 0 0
  • 一、iOS中的沙盒机制 iOS应用程序只能对自己创建的文件系统读取文件,这个独立、封闭、安全的空间,叫做沙盒。它一...
    1d5cb7cff98d阅读 1,760评论 0 0
  • iOS开发-文件管理(一) 一、iOS中的沙盒机制 iOS应用程序只能对自己创建的文件系统读取文件,这个独立、封闭...
    Friez平板支撑阅读 4,584评论 0 1