美文网首页iOS CollectioniOS学习开发好东西
iOS开发之文件相关的操作(沙盒目录,文件创建、移动、复制等)

iOS开发之文件相关的操作(沙盒目录,文件创建、移动、复制等)

作者: 绿豆粥与茶叶蛋 | 来源:发表于2017-05-11 17:24 被阅读471次
    前言

    在iOS开发中我们经常会遇到一些关于文件的操作,比如说:获取沙盒路径、创建文件、删除文件、向文件内写入内容等等。为了方便,这里做一个总结,以便用到的时候可以方便的使用。

    正文

    本文将针对在iOS开发中涉及到的文件相关的操作做一个总结,主要从以下几个方面来讲解:

    • 获取沙盒目录相关路径
    • 创建文件或文件(夹)
    • 写入文件内容
    • 删除文件(夹)
    • 复制文件(夹)
    • 移动文件(夹)
    • 根据URL获取文件名
    • 判断文件(夹)是否存在
    • 获取文件(夹)大小
    • 遍历文件夹
    • 获取文件属性
    1、获取沙盒目录相关路径(沙盒文件结构如图 1-1)
    图1-1 沙盒的结构.png

    获取沙盒的主目录路径:

    + (NSString *)homeDir {
        return NSHomeDirectory();
    }
    

    获取沙盒中Documents的目录路径:

    + (NSString *)documentsDir {
        return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    }
    

    获取沙盒中Library的目录路径:

    + (NSString *)libraryDir {
        return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
    }
    

    获取沙盒中Libarary/Preferences的目录路径:

    + (NSString *)preferencesDir {
        NSString *libraryDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
        return [libraryDir stringByAppendingPathComponent:@"Preferences"];
    }
    

    获取沙盒中Library/Caches的目录路径:

    + (NSString *)cachesDir {
        return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    }
    

    获取沙盒中tmp的目录路径:

    + (NSString *)tmpDir {
        return NSTemporaryDirectory();
    }
    
    2、创建文件(夹)

    创建文件夹:

    + (BOOL)createDirectoryAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        NSFileManager *manager = [NSFileManager defaultManager];
        /* createDirectoryAtPath:withIntermediateDirectories:attributes:error:
         * 参数1:创建的文件夹的路径
         * 参数2:是否创建媒介的布尔值,一般为YES
         * 参数3: 属性,没有就置为nil
         * 参数4: 错误信息
        */
        BOOL isSuccess = [manager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:error];
        return isSuccess;
    }
    

    创建文件:

    /*创建文件
     *参数1:文件创建的路径
     *参数2:写入文件的内容
     *参数3:假如已经存在此文件是否覆盖
     *参数4:错误信息
     */
    + (BOOL)createFileAtPath:(NSString *)path overwrite:(BOOL)overwrite error:(NSError *__autoreleasing *)error {
        // 如果文件夹路径不存在,那么先创建文件夹
        NSString *directoryPath = [self directoryAtPath:path];
        if (![self isExistsAtPath:directoryPath]) {
            // 创建文件夹
            if (![self createDirectoryAtPath:directoryPath error:error]) {
                return NO;
            }
        }
        // 如果文件存在,并不想覆盖,那么直接返回YES。
        if (!overwrite) {
            if ([self isExistsAtPath:path]) {
                return YES;
            }
        }
       /*创建文件
        *参数1:创建文件的路径
        *参数2:创建文件的内容(NSData类型)
        *参数3:文件相关属性
        */
        BOOL isSuccess = [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
    
        return isSuccess;
    }
    
    

    获取文件创建的时间或者修改的时间:

    //获取文件创建的时间
    + (NSDate *)creationDateOfItemAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        return (NSDate *)[self attributeOfItemAtPath:path forKey:NSFileCreationDate error:error];
    }
    
    //获取文件修改的时间
    + (NSDate *)modificationDateOfItemAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        return (NSDate *)[self attributeOfItemAtPath:path forKey:NSFileModificationDate error:error];
    }
    
    3、写入文件内容

    按照文件路径向文件写入内容,内容可为数组、字典、NSData等等:

    #pragma mark 写入文件内容
    /*参数1:文件路径
     *参数2:文件内容
     *参数3:错误信息
     */
    + (BOOL)writeFileAtPath:(NSString *)path content:(NSObject *)content error:(NSError *__autoreleasing *)error {
        //判断文件内容是否为空
        if (!content) {
            [NSException raise:@"非法的文件内容" format:@"文件内容不能为nil"];
            return NO;
        }
        //判断文件(夹)是否存在
        if ([self isExistsAtPath:path]) {
            if ([content isKindOfClass:[NSMutableArray class]]) {//文件内容为可变数组
                [(NSMutableArray *)content writeToFile:path atomically:YES];
            }else if ([content isKindOfClass:[NSArray class]]) {//文件内容为不可变数组
                [(NSArray *)content writeToFile:path atomically:YES];
            }else if ([content isKindOfClass:[NSMutableData class]]) {//文件内容为可变NSMutableData
                [(NSMutableData *)content writeToFile:path atomically:YES];
            }else if ([content isKindOfClass:[NSData class]]) {//文件内容为NSData
                [(NSData *)content writeToFile:path atomically:YES];
            }else if ([content isKindOfClass:[NSMutableDictionary class]]) {//文件内容为可变字典
                [(NSMutableDictionary *)content writeToFile:path atomically:YES];
            }else if ([content isKindOfClass:[NSDictionary class]]) {//文件内容为不可变字典
                [(NSDictionary *)content writeToFile:path atomically:YES];
            }else if ([content isKindOfClass:[NSJSONSerialization class]]) {//文件内容为JSON类型
                [(NSDictionary *)content writeToFile:path atomically:YES];
            }else if ([content isKindOfClass:[NSMutableString class]]) {//文件内容为可变字符串
                [[((NSString *)content) dataUsingEncoding:NSUTF8StringEncoding] writeToFile:path atomically:YES];
            }else if ([content isKindOfClass:[NSString class]]) {//文件内容为不可变字符串
                [[((NSString *)content) dataUsingEncoding:NSUTF8StringEncoding] writeToFile:path atomically:YES];
            }else if ([content isKindOfClass:[UIImage class]]) {//文件内容为图片
                [UIImagePNGRepresentation((UIImage *)content) writeToFile:path atomically:YES];
            }else if ([content conformsToProtocol:@protocol(NSCoding)]) {//文件归档
                [NSKeyedArchiver archiveRootObject:content toFile:path];
            }else {
                [NSException raise:@"非法的文件内容" format:@"文件类型%@异常,无法被处理。", NSStringFromClass([content class])];
                
                return NO;
            }
        }else {
            return NO;
        }
        return YES;
    }
    #pragma mark - 判断文件(夹)是否存在
    + (BOOL)isExistsAtPath:(NSString *)path {
        return [[NSFileManager defaultManager] fileExistsAtPath:path];
    }
    
    4、删除文件(夹)

    删除文件(夹):

    + (BOOL)removeItemAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        return [[NSFileManager defaultManager] removeItemAtPath:path error:error];
    }
    

    清空Caches或者temp文件夹:

    #pragma mark 清空Cashes文件夹
    + (BOOL)clearCachesDirectory {
        NSArray *subFiles = [self listFilesInCachesDirectoryByDeep:NO];
        BOOL isSuccess = YES;
        
        for (NSString *file in subFiles) {
            NSString *absolutePath = [[self cachesDir] stringByAppendingPathComponent:file];
            isSuccess &= [self removeItemAtPath:absolutePath];
        }
        return isSuccess;
    }
    #pragma mark 清空temp文件夹
    + (BOOL)clearTmpDirectory {
        NSArray *subFiles = [self listFilesInTmpDirectoryByDeep:NO];
        BOOL isSuccess = YES;
        
        for (NSString *file in subFiles) {
            NSString *absolutePath = [[self tmpDir] stringByAppendingPathComponent:file];
            isSuccess &= [self removeItemAtPath:absolutePath];
        }
        return isSuccess;
    }
    
    5、复制文件(夹)

    依据源文件的路径复制一份到目标路径:

    #pragma mark - 复制文件
    /*参数1、被复制文件路径
     *参数2、要复制到的目标文件路径
     *参数3、当要复制到的文件路径文件存在,会复制失败,这里传入是否覆盖
     *参数4、错误信息
     */
    + (BOOL)copyItemAtPath:(NSString *)path toPath:(NSString *)toPath overwrite:(BOOL)overwrite error:(NSError *__autoreleasing *)error {
        // 先要保证源文件路径存在,不然抛出异常
        if (![self isExistsAtPath:path]) {
            [NSException raise:@"非法的源文件路径" format:@"源文件路径%@不存在,请检查源文件路径", path];
            return NO;
        }
        //获得目标文件的上级目录
        NSString *toDirPath = [self directoryAtPath:toPath];
        if (![self isExistsAtPath:toDirPath]) {
            // 创建复制路径
            if (![self createDirectoryAtPath:toDirPath error:error]) {
                return NO;
            }
        }
        // 如果覆盖,那么先删掉原文件
        if (overwrite) {
            if ([self isExistsAtPath:toPath]) {
                [self removeItemAtPath:toPath error:error];
            }
        }
        // 复制文件,如果不覆盖且文件已存在则会复制失败
        BOOL isSuccess = [[NSFileManager defaultManager] copyItemAtPath:path toPath:toPath error:error];
        
        return isSuccess;
    }
    
    #pragma mark - 判断文件(夹)是否存在
    + (BOOL)isExistsAtPath:(NSString *)path {
        return [[NSFileManager defaultManager] fileExistsAtPath:path];
    }
    
    6、 移动文件(夹)

    依据源文件的路径移动到目标路径:

    #pragma mark - 移动文件(夹)
    /*参数1、被移动文件路径
     *参数2、要移动到的目标文件路径
     *参数3、当要移动到的文件路径文件存在,会移动失败,这里传入是否覆盖
     *参数4、错误信息
     */
    + (BOOL)moveItemAtPath:(NSString *)path toPath:(NSString *)toPath overwrite:(BOOL)overwrite error:(NSError *__autoreleasing *)error {
        // 先要保证源文件路径存在,不然抛出异常
        if (![self isExistsAtPath:path]) {
            [NSException raise:@"非法的源文件路径" format:@"源文件路径%@不存在,请检查源文件路径", path];
            return NO;
        }
        //获得目标文件的上级目录
        NSString *toDirPath = [self directoryAtPath:toPath];
        if (![self isExistsAtPath:toDirPath]) {
            // 创建移动路径
            if (![self createDirectoryAtPath:toDirPath error:error]) {
                return NO;
            }
        }
        // 判断目标路径文件是否存在
        if ([self isExistsAtPath:toPath]) {
            //如果覆盖,删除目标路径文件
            if (overwrite) {
                //删掉目标路径文件
                [self removeItemAtPath:toPath error:error];
            }else {
               //删掉被移动文件
                [self removeItemAtPath:path error:error];
                return YES;
            }
        }
        
        // 移动文件,当要移动到的文件路径文件存在,会移动失败
        BOOL isSuccess = [[NSFileManager defaultManager] moveItemAtPath:path toPath:toPath error:error];
        
        return isSuccess;
    }
    
    7、根据URL获取文件名

    根据文件路径获取文件名称,是否需要后缀:

    #pragma mark - 根据URL获取文件名
    /*参数1:文件路径
     *参数2、是否需要后缀
     */
    + (NSString *)fileNameAtPath:(NSString *)path suffix:(BOOL)suffix {
        NSString *fileName = [path lastPathComponent];
        if (!suffix) {
            fileName = [fileName stringByDeletingPathExtension];
        }
        return fileName;
    }
    

    获取文件所在的文件夹路径:

    + (NSString *)directoryAtPath:(NSString *)path {
        return [path stringByDeletingLastPathComponent];
    }
    

    根据文件路径获取文件扩展类型:

    + (NSString *)suffixAtPath:(NSString *)path {
        return [path pathExtension];
    }
    
    8、判断文件(夹)是否存在

    判断文件路径是否存在:

    + (BOOL)isExistsAtPath:(NSString *)path {
        return [[NSFileManager defaultManager] fileExistsAtPath:path];
    }
    

    判断路径是否为空(判空条件是文件大小为0,或者是文件夹下没有子文件):

    + (BOOL)isEmptyItemAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        return ([self isFileAtPath:path error:error] &&
                [[self sizeOfItemAtPath:path error:error] intValue] == 0) ||
        ([self isDirectoryAtPath:path error:error] &&
         [[self listFilesInDirectoryAtPath:path deep:NO] count] == 0);
    }
    

    判断目录是否是文件夹:

    + (BOOL)isDirectoryAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        return ([self attributeOfItemAtPath:path forKey:NSFileType error:error] == NSFileTypeDirectory);
    }
    

    判断目录是否是文件:

    + (BOOL)isFileAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        return ([self attributeOfItemAtPath:path forKey:NSFileType error:error] == NSFileTypeRegular);
    }
    

    判断目录是否可以执行:

    + (BOOL)isExecutableItemAtPath:(NSString *)path {
        return [[NSFileManager defaultManager] isExecutableFileAtPath:path];
    }
    

    判断目录是否可读:

    + (BOOL)isReadableItemAtPath:(NSString *)path {
        return [[NSFileManager defaultManager] isReadableFileAtPath:path];
    }
    

    判断目录是否可写:

    + (BOOL)isWritableItemAtPath:(NSString *)path {
        return [[NSFileManager defaultManager] isWritableFileAtPath:path];
    }
    
    9、获取文件(夹)大小

    获取文件大小(NSNumber):

    + (NSNumber *)sizeOfItemAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        return (NSNumber *)[self attributeOfItemAtPath:path forKey:NSFileSize error:error];
    }
    

    获取文件夹大小(NSNumber):

    #pragma mark 获取文件夹的大小
    + (NSNumber *)sizeOfDirectoryAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        if ([self isDirectoryAtPath:path error:error]) {
           //深遍历文件夹
            NSArray *subPaths = [self listFilesInDirectoryAtPath:path deep:YES];
            NSEnumerator *contentsEnumurator = [subPaths objectEnumerator];
            
            NSString *file;
            unsigned long long int folderSize = 0;
            
            while (file = [contentsEnumurator nextObject]) {
                NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[path stringByAppendingPathComponent:file] error:nil];
                folderSize += [[fileAttributes objectForKey:NSFileSize] intValue];
            }
            return [NSNumber numberWithUnsignedLongLong:folderSize];
        }
        return nil;
    }
    

    获取文件大小(单位为字节):

    + (NSString *)sizeFormattedOfItemAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        //先获取NSNumber类型的大小
        NSNumber *size = [self sizeOfItemAtPath:path error:error];
        if (size) {
           //将文件大小格式化为字节
            return [self sizeFormatted:size];
        }
        return nil;
    }
    
    #pragma mark 将文件大小格式化为字节
    +(NSString *)sizeFormatted:(NSNumber *)size {
        /*NSByteCountFormatterCountStyle枚举
         *NSByteCountFormatterCountStyleFile 字节为单位,采用十进制的1000bytes = 1KB
         *NSByteCountFormatterCountStyleMemory 字节为单位,采用二进制的1024bytes = 1KB
         *NSByteCountFormatterCountStyleDecimal KB为单位,采用十进制的1000bytes = 1KB
         *NSByteCountFormatterCountStyleBinary KB为单位,采用二进制的1024bytes = 1KB
         */
        return [NSByteCountFormatter stringFromByteCount:[size unsignedLongLongValue] countStyle:NSByteCountFormatterCountStyleFile];
    }
    

    获取文件夹大小(单位为字节):

    + (NSString *)sizeFormattedOfDirectoryAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        //先获取NSNumber类型的大小
        NSNumber *size = [self sizeOfDirectoryAtPath:path error:error];
        if (size) {
            return [self sizeFormatted:size];
        }
        return nil;
    }
    #pragma mark 将文件大小格式化为字节
    +(NSString *)sizeFormatted:(NSNumber *)size {
        /*NSByteCountFormatterCountStyle枚举
         *NSByteCountFormatterCountStyleFile 字节为单位,采用十进制的1000bytes = 1KB
         *NSByteCountFormatterCountStyleMemory 字节为单位,采用二进制的1024bytes = 1KB
         *NSByteCountFormatterCountStyleDecimal KB为单位,采用十进制的1000bytes = 1KB
         *NSByteCountFormatterCountStyleBinary KB为单位,采用二进制的1024bytes = 1KB
         */
        return [NSByteCountFormatter stringFromByteCount:[size unsignedLongLongValue] countStyle:NSByteCountFormatterCountStyleFile];
    }
    
    10、遍历文件夹

    遍历文件夹,分为深遍历和浅遍历:

    #pragma mark - 遍历文件夹
    /**
     文件遍历
     参数1:目录的绝对路径
     参数2:是否深遍历 (1. 浅遍历:返回当前目录下的所有文件和文件夹;
     2. 深遍历:返回当前目录下及子目录下的所有文件和文件夹)
     */
    + (NSArray *)listFilesInDirectoryAtPath:(NSString *)path deep:(BOOL)deep {
        NSArray *listArr;
        NSError *error;
        NSFileManager *manager = [NSFileManager defaultManager];
        if (deep) {
            // 深遍历
            NSArray *deepArr = [manager subpathsOfDirectoryAtPath:path error:&error];
            if (!error) {
                listArr = deepArr;
            }else {
                listArr = nil;
            }
        }else {
            // 浅遍历
            NSArray *shallowArr = [manager contentsOfDirectoryAtPath:path error:&error];
            if (!error) {
                listArr = shallowArr;
            }else {
                listArr = nil;
            }
        }
        return listArr;
    }
    
    
    11、获取文件属性

    根据key获取文件某个属性:

    //key的列表如:
    FOUNDATION_EXPORT NSString * const NSFileType;
    FOUNDATION_EXPORT NSString * const NSFileTypeDirectory;
    FOUNDATION_EXPORT NSString * const NSFileTypeRegular;
    FOUNDATION_EXPORT NSString * const NSFileTypeSymbolicLink;
    FOUNDATION_EXPORT NSString * const NSFileTypeSocket;
    FOUNDATION_EXPORT NSString * const NSFileTypeCharacterSpecial;
    FOUNDATION_EXPORT NSString * const NSFileTypeBlockSpecial;
    FOUNDATION_EXPORT NSString * const NSFileTypeUnknown;
    FOUNDATION_EXPORT NSString * const NSFileSize;
    FOUNDATION_EXPORT NSString * const NSFileModificationDate;
    FOUNDATION_EXPORT NSString * const NSFileReferenceCount;
    FOUNDATION_EXPORT NSString * const NSFileDeviceIdentifier;
    FOUNDATION_EXPORT NSString * const NSFileOwnerAccountName;
    FOUNDATION_EXPORT NSString * const NSFileGroupOwnerAccountName;
    FOUNDATION_EXPORT NSString * const NSFilePosixPermissions;
    FOUNDATION_EXPORT NSString * const NSFileSystemNumber;
    FOUNDATION_EXPORT NSString * const NSFileSystemFileNumber;
    FOUNDATION_EXPORT NSString * const NSFileExtensionHidden;
    FOUNDATION_EXPORT NSString * const NSFileHFSCreatorCode;
    FOUNDATION_EXPORT NSString * const NSFileHFSTypeCode;
    FOUNDATION_EXPORT NSString * const NSFileImmutable;
    FOUNDATION_EXPORT NSString * const NSFileAppendOnly;
    FOUNDATION_EXPORT NSString * const NSFileCreationDate;
    FOUNDATION_EXPORT NSString * const NSFileOwnerAccountID;
    FOUNDATION_EXPORT NSString * const NSFileGroupOwnerAccountID;
    FOUNDATION_EXPORT NSString * const NSFileBusy;
    FOUNDATION_EXPORT NSString * const NSFileProtectionKey NS_AVAILABLE_IOS(4_0);
    FOUNDATION_EXPORT NSString * const NSFileProtectionNone NS_AVAILABLE_IOS(4_0);
    FOUNDATION_EXPORT NSString * const NSFileProtectionComplete NS_AVAILABLE_IOS(4_0);
    FOUNDATION_EXPORT NSString * const NSFileProtectionCompleteUnlessOpen NS_AVAILABLE_IOS(5_0);
    FOUNDATION_EXPORT NSString * const NSFileProtectionCompleteUntilFirstUserAuthentication NS_AVAILABLE_IOS(5_0);
    
    + (id)attributeOfItemAtPath:(NSString *)path forKey:(NSString *)key error:(NSError *__autoreleasing *)error {
        return [[self attributesOfItemAtPath:path error:error] objectForKey:key];
    }
    

    获取文件属性集合:

    + (NSDictionary *)attributesOfItemAtPath:(NSString *)path error:(NSError *__autoreleasing *)error {
        return [[NSFileManager defaultManager] attributesOfItemAtPath:path error:error];
    }
    

    源码已上传至fenglinyunshi-git,欢迎下载,并提出宝贵意见。

    结语:

    本篇详细的讲解了iOS开发中所可能涉及到的有关文件或者文件夹相关的操作,比如:沙盒路径的获取、文件创建、文件删除、复制、移动等等操作。本篇所属的具体的代码实现存在很多函数建相互调用的情况,还请阅读时了解。对于上面关于文件的所有操作封装了一个工具类,已上传git欢迎下载使用。

    生命哪,并不是你活了多少日子,而是你记住了多少日子,要使你过的每一天都值得回忆。

    相关文章

      网友评论

      • footSInRoad:嗯嗯 好的我看看 谢谢啦😊
      • footSInRoad:谢谢分享 另外想问一下 app可以访问这个app以外的空间么?比如qq想获取微信中的一个pdf文件?
        绿豆粥与茶叶蛋:@不以物喜_不以己悲 一般比如微信或qq接收到文件点击文件后点右上角不是有个ActionSheet嘛,那里有个用其他应用打开的选项,可以考虑把自己的app加在这个选项里,打开到自己的app时,要截取到过来资源的文件路径,然后操作,可以参考一下文章http://blog.csdn.net/totogo2010/article/details/29182385,这个方案应该可行。
        footSInRoad:比如说我想上传一个附件到我的app上怎么实现啊? 现在经理有这样的要求。。还请提供个思路,或者有哪些资料可以参考。谢了
        绿豆粥与茶叶蛋:@不以物喜_不以己悲 不可以 都有沙盒机制保护的,每个app都是封闭独立的

      本文标题:iOS开发之文件相关的操作(沙盒目录,文件创建、移动、复制等)

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