Swift&OC 文件夹和文件的详细操作(上)

简介: Swift&OC 文件夹和文件的详细操作

建议大家看 JKSwiftExtension,测试用例在 FileManagerExtensionViewController ,是关于沙盒的操作


在iOS开发我们会遇到文件、音频、视频等等下载后本地存储的情况,这时对读文件,写文件就显得很重要,对文件夹以及文件中的文件的操作,这时就可以使用NSFileManager(FileManager)或NSFileHandle(FileHandle)来实现。下面会用OC和Swift的对比来实现对文件和文件夹的操作


  • 文件管理器(NSFileManager/FileManager):此类主要是对文件进行的操作(创建/删除/改名等)以及文件信息的获取。
  • 文件连接器(NSFileHandle/FileHandle):此类主要是对文件内容进行读取和写入操作。


一、沙盒以及组成部分



iOS应用程序只能对自己创建的文件系统读取文件,这个"独立","封闭","安全"的空间,称之为沙盒。


  • 1.1、Home目录(应用程序包)
  • 整个应用程序各文档所在的目录,包含了所有的资源文件和可执行文件
  • 1.2、Documents
  • 保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录
  • 需要保存由"应用程序本身"产生的文件或者数据,例如: 游戏进度,涂鸦软件的绘图
  • 目录中的文件会被自动保存在 iCloud
  • 注意: 不要保存从网络上下载的文件,否则会无法上架!
  • 1.3、tmp
  • 保存应用运行时所需要的临时数据或文件,"后续不需要使用",使用完毕后再将相应的文件从该目录删除。
  • 应用没有运行,系统也可能会清除该目录下的文件
  • iTunes不会同步备份该目录
  • 重新启动手机, tmp 目录会被清空
  • 系统磁盘空间不足时,系统也会自动清理
  • 1.4、Library/Cache
  • 保存应用运行时生成的需要持久化的数据,iTunes同步设备时不备份该目录。一般存放体积大、不需要备份的非重要数据
  • 保存临时文件,"后续需要使用",例如: 缓存的图片,离线数据(地图数据)
  • 系统不会清理 cache 目录中的文件
  • 就要求程序开发时, "必须提供 cache 目录的清理解决方案"
  • 1.5、Library/Preference
  • 保存应用的所有偏好设置,IOS的Settings应用会在该目录中查找应用的设置信息。iTunes
  • 用户偏好,使用 NSUserDefault 直接读写!
  • 如果想要数据及时写入硬盘,还需要调用一个同步方法 synchronize()
  • 1.6.程序.app,与另三个路径的父路径不同
  • 这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以您在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动


二、对文件以及文件夹的操作



2.1、获取各个目录的路径


  • 2.1.1、HomeDirectory
OC:                
NSString *filePath = NSHomeDirectory();
Swift:
let homePath = NSHomeDirectory()
  • 2.1.2、Documents
OC:                
方法一
NSString * documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0]; 
方法二
NSString * documentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
Swift:
方法1
let documentsPaths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentsPath = documentPaths[0]
方法2
let documentsPath = NSHomeDirectory()+"/Documents"
  • 2.1.3、Caches
OC:  
方法一
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
方法二
NSString *cachesPath= [NSHomeDirectory() stringByAppendingPathComponent:@"/Library/Caches"];             
Swift:
方法1
let cachePaths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let cachePath = cachePaths.last
方法2
let cachePath = NSHomeDirectory()+"/Library/Caches"
  • 2.1.4、Library
OC:  
方法一
NSString * libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
方法二
NSString * libraryPath = [NSHomeDirectory() stringByAppendingPathComponent:@"/Library"];
Swift:
方法1
let libraryPaths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.libraryDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let libraryPath = libraryPaths[0]
方法2
let libraryPath = NSHomeDirectory()+"/Library"
  • 2.1.5、tmp
OC:  
方法一
NSString *tempPath = NSTemporaryDirectory();
方法二
NSString * tempPath = [NSHomeDirectory() stringByAppendingPathComponent:@"/tmp"];
Swift:
方法1
let tempPath = NSTemporaryDirectory()
方法2
let tempPath = NSHomeDirectory()+"/tmp"


2.2、根据传件来的路径创建文件夹 创建文件目录(蓝色的,文件夹和文件是不一样的)

应用程序目录, Caches、Library、Documents目录文件夹下创建文件夹(蓝色的)

下面以Documents为例创建JKFile为例

image.png

  • OC
NSString *filePath=[NSHomeDirectory() stringByAppendingPathComponent:@"Documents/JKFile"];
- (NSString *)jKCreateDir:folderName{
    NSString *filePath=[NSHomeDirectory() stringByAppendingPathComponent: folderName];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isDir = NO;
    // fileExistsAtPath 判断一个文件或目录是否有效,isDirectory判断是否一个目录
    BOOL existed = [fileManager fileExistsAtPath:filePath isDirectory:&isDir];
    if ( !(isDir == YES && existed == YES) ) {
      // 不存在的路径才会创建
      [fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
    }
  return filePath;
}
  • Swift:
let jKFilePath = NSHomeDirectory() + "/Documents/JKFile";
func jKCreateFolder(folderName: NSString) -> NSString {
   let fileManager: FileManager = FileManager.default
   let filePath = "\(folderName)"
   let exist = fileManager.fileExists(atPath: filePath)
   // 不存在的路径才会创建
   if (!exist) {
    //withIntermediateDirectories为ture表示路径中间如果有不存在的文件夹都会创建
    try! fileManager.createDirectory(atPath: filePath,withIntermediateDirectories: true, attributes: nil)
    }
  return filePath as NSString
 }


2.3、删除文件夹(先判断文件夹存不存在)
  • OC
NSString *filePath=[NSHomeDirectory() stringByAppendingPathComponent:@"Documents/JKFile"];
- (void)jKRemovefolder:(NSString *)filePathName {
    // filePath: 文件/目录的路径
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *filePath = [NSString stringWithFormat:@"%@",filePathName];
    BOOL isDir = NO;
    // fileExistsAtPath 判断一个文件或目录是否有效,isDirectory判断是否一个目录
    BOOL existed = [fileManager fileExistsAtPath:filePath isDirectory:&isDir];
    if ( !(isDir == YES && existed == YES) ) {
      // 不存在的路径才会创建
      return;
    }
   //文件夹
   [fileManager removeItemAtPath:filePath error:nil];
}
  • Swift:
let jKFilePath = NSHomeDirectory() + "/Documents/JKFile";
func jKRemovefolder(folderName: NSString){
   let fileManager: FileManager = FileManager.default
   let filePath = "\(folderName)"
   let exist = fileManager.fileExists(atPath: filePath)
   // 查看文件夹是否存在,如果存在就直接读取,不存在就直接反空
   if (exist) {
      try! fileManager.removeItem(atPath: filePath)
   }else{
     // 不存在就不做什么操作了
   }
}


2.4、删除文件
  • OC
- (void)jKRemovefile:(NSString *)filePathName {
     // filePath: 文件/目录的路径
     NSFileManager *fileManager = [NSFileManager defaultManager];
     NSString *filePath = [NSString stringWithFormat:@"%@",filePathName];
    //移除文件
   [fileManager removeItemAtPath:filePath error:nil];
}
  • Swift:
func jKRemovefile(folderName: NSString){
   let fileManager: FileManager = FileManager.default
   let filePath = "\(folderName)"
   //移除文件
   try! fileManager.removeItem(atPath: filePath)
 }


2.5、深度遍历(搜索文件夹)


  • 2.5.1、深度搜索遍历一(subpathsAtPath)深度遍历,会递归遍历子文件夹(包括符号链接,所以要求性能的话用enumeratorAtPath)


image.png

  • 获取某个文件下的所有文件的名字
  • OC
NSString *filePath = NSHomeDirectory();
-(NSArray *)jKGetAllFileNames:(NSString *)folderName
{
  NSFileManager *fileManager = [NSFileManager defaultManager];
  // 取得一个目录下得所有文件名
  NSArray *files = [fileManager subpathsAtPath:[self jKCreateFolder:folderName]];
  //NSLog(@"pdf名字的数量=%ld 数组=%@",files.count,files);
  return files;
}
  • Swift:
let jKFilePath = NSHomeDirectory();
func jKGetAllFileNames(folderName: NSString) -> NSArray{
  let filePath = "\(folderName)"
  let exist = fileManager.fileExists(atPath: filePath)
  // 查看文件夹是否存在,如果存在就直接读取,不存在就直接反空
  if (exist) {
     let subPaths = fileManager.subpaths(atPath: folderName as String)
      return subPaths! as NSArray
  }else{
      return []
  }
}
  • 2.5.2、深度遍历二,会递归遍历子文件夹(但不会递归符号链接)
  • OC
// folderNmae:文件夹的名字
-(NSArray *)jKDeepSearchEnumeratorAllFileNames:(NSString *)folderName{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    // 取得一个目录下得所有文件名
    NSDirectoryEnumerator *files = [fileManager enumeratorAtPath:[self jKCreateFolder:folderName]];
    //NSLog(@"pdf名字的数量=%ld 数组=%@",files.count,files);
    return files.allObjects;
 }
  • Swift:
func jKDeepSearchAllFiles(folderName: NSString) -> NSArray
{
    let filePath = "\(folderName)"
    let exist = fileManager.fileExists(atPath: filePath)
    // 查看文件夹是否存在,如果存在就直接读取,不存在就直接反空
    if (exist) {
       let contentsOfPathArray = fileManager.enumerator(atPath: filePath)
       return contentsOfPathArray!.allObjects as NSArray
    }else{
       return []
    }
}


2.6、对指定路径执行浅搜索,返回指定目录路径下的文件、子目录及符号链接的列表(只寻找一层)


image.png

  • OC
/**对指定路径执行浅搜索,返回指定目录路径下的文件、子目录及符号链接的列表(只寻找一层)*/
NSString *customPath = [NSString stringWithFormat:@"%@",[JKFilePathOperationExtension jKHomeDirectory]];
-(NSArray *)jKShallowSearchAllFiles:(NSString *)filePath{
     NSFileManager *fileManager = [NSFileManager defaultManager];
     NSArray *contentsOfPathArray = [fileManager contentsOfDirectoryAtPath:filePath error:nil];
     return contentsOfPathArray;
 }
  • Swift:
/** 对指定路径执行浅搜索,读取指定目录路径下的文件、子目录及符号链接的列表(只寻找一层)*/
let jKFilePath = NSHomeDirectory()
func jKShallowSearchAllFiles(folderName: NSString) -> NSArray {
    let filePath = "\(folderName)"
    let contentsOfPathArray = try! fileManager.contentsOfDirectory(atPath: filePath);
    return contentsOfPathArray as NSArray
 }


2.7、判断文件或文件夹是否存在
  • OC
+(BOOL)jkJudgeFileOrFolderExists:(NSString *)filePathName{
   NSFileManager *fileManager = [NSFileManager defaultManager];
   NSString *filePath = [NSString stringWithFormat:@"%@",filePathName];
   BOOL isDir = NO;
   // fileExistsAtPath 判断一个文件或目录是否有效,isDirectory判断是否一个目录
   BOOL existed = [fileManager fileExistsAtPath:filePath isDirectory:&isDir];
   if ( !(isDir == YES && existed == YES) ) {
        // 不存在的路径
        return NO;
   }else{
       return YES;
   }
  return nil;
}
  • Swift:
func jkJudgeFileOrFolderExists(folderName: NSString) -> Bool
 {
    let filePath = "\(folderName)"
    let exist = fileManager.fileExists(atPath: filePath)
    // 查看文件夹是否存在,如果存在就直接读取,不存在就直接反空
    if (exist) {
       return true
    }else{
      return false
    }
 }


2.8、创建文件(如:动画乐园.text格式的文本文件)


image.png

  • OC
/**folderNmae:文件的名字*/
- (NSString *)jKCreateFile:(NSString *)folderName{
    NSString *filePath = [NSString stringWithFormat:@"%@",folderName];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isDir = NO;
    // fileExistsAtPath 判断一个文件或目录是否有效,isDirectory判断是否一个目录
    BOOL existed = [fileManager fileExistsAtPath:filePath isDirectory:&isDir];
    if ( !(isDir == YES && existed == YES) ) {
         // 不存在的路径才会创建
         [fileManager createFileAtPath:filePath contents:nil attributes:nil];
     }
   return filePath;
}
  • Swift:
// fileName:文件的名字(不是文件夹)
 // baseFilePath: 文件的基础路径
 // content: 存进文件的内容
 /** 根据传件来的路径创建文件*/
 func jKCreateFile(fileName: NSString,baseFilePath: NSString) -> (filePath: NSString,createStatus: Bool) {
   // NSHomeDirectory():应用程序目录
   let filePath = "\(baseFilePath)" + "/\(fileName)"
   let exist = fileManager.fileExists(atPath: filePath)
   // 不存在的文件路径才会创建
   if (!exist) {
       //withIntermediateDirectories为ture表示路径中间如果有不存在的文件夹都会创建
       let createSuccess = fileManager.createFile(atPath: filePath,contents:nil,attributes:nil)
       return (filePath as NSString,createSuccess as Bool)
    }
   return (filePath as NSString,true)
 }


2.9、可以通过write(to:)方法,可以创建文件并将对象(文件,音频,图片,视频以及数组,字典)都可以写入文件


  • 简单对象:iOS中提供四种类型可以直接进行文件存取:NSString(字符串)、NSArray(数组)、NSDictionary(字典)、NSData(数据)(以上类型包括子类)
  • 注意:数组(可变与不可变)和字典(可变与不可变)中元素对象的类型,也必须是上述四种,否则不能直接写入文件
  • 2.9.1、把NSSString保存到上面“动画乐园.text”的文件里面


image.png

image.png

目录
相关文章
|
6月前
|
Swift Perl
OC和swift混合工程更新库时报:target has transitive dependencies that include statically linked binaries
OC和swift混合工程更新库时报:target has transitive dependencies that include statically linked binaries
92 0
|
API Swift iOS开发
45 Swift和OC的混编
Swift和OC的混编
122 0
|
Swift iOS开发
iOS OC混编Swift 后者无法走断点
iOS OC混编Swift 后者无法走断点
80 0
|
Swift iOS开发
IOS使用Swift加载Xib文件
IOS使用Swift加载Xib文件
323 0
|
Swift
《OpenStack Swift 海量小文件优化之路》电子版地址
OpenStack Swift 海量小文件优化之路
81 0
《OpenStack Swift 海量小文件优化之路》电子版地址
|
Swift iOS开发
Swift - 与OC混编时如何创建桥接头文件
Swift - 与OC混编时如何创建桥接头文件
463 0
Swift - 与OC混编时如何创建桥接头文件
|
Swift
Swift和OC控制器互相跳转
Swift和OC控制器互相跳转
319 0
|
Swift
Swift - pods中导入的Object-C文件在桥接文件中写入找不到的问题
Swift - pods中导入的Object-C文件在桥接文件中写入找不到的问题
146 0
|
Swift
OC 和 swift 创建单例方法
OC 和 swift 创建单例方法
326 0
|
Swift iOS开发
Swift与OC的混编
Swift调用OC文件 OC调用Swift文件
378 0
Swift与OC的混编