在最近开发的项目中,有这样一项需求,我需要获得一个文件夹下的全部文件的文件名称,然后对每个文件进行一些处理。
查阅资料发现,可以通过NSFileManager进行 *** 作。于是我采用了如下代码解决问题。
(这段代码也是CV大法来的哦,原文链接:iOS 递归遍历文件夹及其子集下的所有文件_icefishlily的博客-CSDN博客_ios 递归遍历)
NSFileManager * fileManger = [NSFileManager defaultManager];
BOOL isDir = NO;
BOOL isExist = [fileManger fileExistsAtPath:path isDirectory:&isDir];
if (isExist) {
if (isDir) {
NSArray * dirArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
NSString * subPath = nil;
for (NSString * str in dirArray) {
subPath = [path stringByAppendingPathComponent:str];
BOOL issubDir = NO;
[fileManger fileExistsAtPath:subPath isDirectory:&issubDir];
[self loadAllFileWithPath:subPath];
}
}else{
NSString *fileName = [[path componentsSeparatedByString:@"/"] lastObject];
if (![fileName hasSuffix:@".json"] && ![fileName hasPrefix:@".DS_Store"]) {
[self splitFileName:fileName];
}else{
[self parseUserJson:fileName];
}
}
}else{
NSLog(@"this path is not exist!");
}
可以看出,我这段代码的作用是是在参数path代表的文件夹路径下进行文件搜索,将除了json和.DS_store之外的文件进行splitFileName处理(这个是我自定义的处理文件名函数)。然后将json和.DS_store文件进行parseUserJson处理(这个是我自定义的处理用户文件代码)。
结果执行一看,处理文件处理了个寂寞,检查路径没写错(开发期间为了验证功能可行性我直接写的绝对路径)。无奈,只好打个断点康康了。
断在如下位置,得到反馈:
有问题,属实有问题。这里竟然是个nil,按理来说,就算是没文件也应该是个0 elements的数组,这里是个nil说明函数执行就有问题,我们传个error进去康康代码执行的正常不正常。
好了,果不其然。错误代码257,错误信息谜语人看不懂,百度一下,从这篇文章(NSCocoaErrorDomain错误码解析 - 简书)里得知 ,原来是权限问题导致的读取问题。
然后又开始了漫长了查询资料阶段,然后发现,OC其实是存在沙盒机制的,一个APP在运行时,只能在它沙盒范围下进行文件处理,沙盒外的文件一概不能碰。
(话说之前写的一个工程也有类似的绝对路径读写文件需求,却没遇到这个问题)
好吧,涨姿势了,那就看看沙盒路径在哪呗,一查发现,可以通过NSHomeDirectory方法来获取到沙盒所在的路径,一试,果不其然,在这里就可以读取到。
经过我的实验,发现在Xcode编译出来的可执行文件中,右键显示包内容,然后其下面的路径也能够正常访问(看了一下路径,应该是和上面方法获取到的沙盒路径不一样,怎么会事呢),就像这样:
真让人摸不着头脑,但是总算是解决了读取不到文件的问题。
然后呢,读取完了,得 *** 作文件了,光读不写非英雄也!开整。
这次的需求是把上面读取到的文件进行筛选,然后挑选一个粘贴到别的路径下。
目标路径是上面说的Xcode编译出来的可执行文件包里的另一个app包里的资源路径(很绕对不对,其实就是工程的资源里又个app包,替换其下的资源)。
至于复制方法呢,这里有两种思路:
其一是采用copyItemAtPath这个接口,将文件从原路径拷贝到目标路径。
这个接口可以这么调用
[[NSFileManager defaultManager] copyItemAtPath:path toPath:targetPath error:nil];
将文件从path拷贝到targetPath路径中。
!注意:这里的targetPath必须以文件名结尾而不是以文件夹名
不然就会这样。
516错误代码,回到上面的文章看一下,是 写错误(文件存在)
因为你指定的文件夹肯定是存在的,你要指定一个目标文件夹下不存在(不与已有文件名重复)的文件名,这样文件就会以你指定的名字复制到目标文件夹。
第二种方法呢,我们可以读取文件的内容,然后将其写入目标文件夹下的文件中。
这里就直接用writeToFile接口好了,就不多说了。
但是呢,我又失败了,没错,又失败了。
如下图所示的错误:
513,老规矩,查一下,是 写错误(权限问题)
啊?能读不能写是吧。这咋办呢,还对读写的权限有区分。
其实到这里我已经失去耐心了,毕竟工期有限,不好耽误太多时间,还记得我上面说的之前的工程没有遇到绝对路径读取问题吗,我直接复制了一份那个工程,然后清空里面的代码,将这个工程代码粘贴进去,顺利的跑起来了,全写的包外绝对路径,既没读取权限问题,也没写权限问题。真是离天下之大谱。跑代码果然是玄学。
但是,这问题也不好扔在这不管了,万一以后遇到不能替换工程解决的情况呢,所以今天就来继续探索一下怎么解决。
找回之前的工程跑一下,嗯,错误代码513,还是原汁原味的权限问题。
猜测是仍旧是沙盒问题,毕竟一个APP发出来不能让你狂自定义写包内文件才合理。
所以我们的工程也不能渗透到资源下的包里写包里的文件,但是既然另一个工程不受影响,那就说明是可解的,我们去了解一下沙盒,看看有没有解决办法。
然后经过一番查资料和比对,发现原来sandBox是可以取消掉的。
在下图所示的地方
看见App SandBox右边那个叉没,按下这个按钮,万事皆休,啊不对,完美解决。
叉掉之后在之前的地方断一下再看。
好耶,错误没了,对应文件夹下文件也复制出来了。
啊……原来我当时搞这么多,结果正确答案就这么一步啊。。。解决问题本来该轻松的时刻却感觉很😓,可能这就是程序员吧。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)