美文网首页
iOS沙盒操作 NSFileManager

iOS沙盒操作 NSFileManager

作者: 炸街程序猿 | 来源:发表于2020-06-11 14:24 被阅读0次

    沙盒机制

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

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

    image

    Documents

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

    Library

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

    tmp

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

    如何查看该目录?

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

    image.png

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

    image.png

    获取相关目录

    // 获取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 关闭文件

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

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

    存:

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

    取:

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

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

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

    两个方法

    相关文章

      网友评论

          本文标题:iOS沙盒操作 NSFileManager

          本文链接:https://www.haomeiwen.com/subject/rbdbtktx.html