zoukankan      html  css  js  c++  java
  • iOS中使用c函数快速获取一个目录所占的空间大小

    原文地址:http://blog.yorkgu.me/2011/12/31/ios-fast-get-folder-size-using-c-code/

    在编写iOS应用时,我们都会大量把服务器的接口调用数据或者图片数据进行缓存,为了更好的使用体验,有时候我们也会把各种缓存的数据所占的空间大小告诉用户,提供给用户参考,并让用户可以手动清除缓存数据,就像我们在千寻影视中也就提供了这样一个设置项。但是当数据多了之后,就会发现所占空间的大小计算非常耗时,因为缓存下来的是大量的小文件,这就会造成界面很久没有反映的状况。为了解决这种情况,当然是可以通过多线程的方法来做到的,但是在一个简单的设置界面做这么复杂的事情,我倒认为是一个拿起牛刀来杀鸡的行为了。本篇就是来探求一些优化手段,把目录的大小计算耗时降到可以接受的程度。

    首先,在iOS当中,要实现一个功能,肯定想到去找objective-c的官方库中是否提供了相关功能,如果有,那就直接用objective-c代码来实现了,通过搜索,很容易就写出这样一个函数:

    1 + (long long) fileSizeAtPath:(NSString*) filePath{
    2     NSFileManager* manager = [NSFileManager defaultManager];
    3     if ([manager fileExistsAtPath:filePath]){
    4         return [[manager attributesOfItemAtPath:filePath error:nil] fileSize];
    5     }
    6     return 0;
    7 }

    简单可行,但是,我们这里探讨性能,要优化,很容易想到直接使用c代码,跳过objective-c的封装来做,于是,我们这个函数就变成了:

    1 + (long long) fileSizeAtPath:(NSString*) filePath{
    2   struct stat st;
    3   if(lstat([filePath cStringUsingEncoding:NSUTF8StringEncoding], &st) == 0){
    4     return st.st_size;
    5   }
    6   return 0;
    7 }

    循环1000次,我们就可以发现两者之间巨大的性能差距了,在我的测试环境中,结果如下,c函数的耗时仅是第一种方法的5%

    2011-12-31 14:17:22.165 otest[85861:903] [<span style="color: #5d68fc;">0.041</span>] 使用NSFileManager获取文件大小
    2011-12-31 14:17:22.168 otest[85861:903] [<span style="color: #5e6cfc;">0.002</span>] 使用unix c函数获取文件大小

    要获取一个目录的总大小,我们就可以写这么一个函数了:

    // 循环调用fileSizeAtPath来获取一个目录所占空间大小
    + (long long) folderSizeAtPath2:(NSString*) folderPath{
      NSFileManager* manager = [NSFileManager defaultManager];
      if (![manager fileExistsAtPath:folderPath]) return 0;
      NSEnumerator *childFilesEnumerator = [[manager subpathsAtPath:folderPath] objectEnumerator];
      NSString* fileName;
      long long folderSize = 0;
      while ((fileName = [childFilesEnumerator nextObject]) != nil){
        NSString* fileAbsolutePath = [folderPath stringByAppendingPathComponent:fileName];
        folderSize += [self fileSizeAtPath:fileAbsolutePath];
      }
      return folderSize;
    }

    但是,通过测试,目录遍历本身所带来的时间消耗大大的弱化了我们改进过的fileSizeAtPath函数所带来的优势,导致后者的测试耗时仅是前者的1/2到1/3之间:

    2011-12-31 14:17:23.233 otest[85861:903] [<span style="color: #4958fc;">0.932</span>] 使用subpathsAtPath然后循环调用NSFileManager获取目录总大小
    2011-12-31 14:17:23.582 otest[85861:903] [<span style="color: #4958fc;">0.348</span>] 使用subpathsAtPath然后循环调用unix c函数获取目录总大小

    既然文件大小的获取可以使用c函数,那么目录的遍历当然可以使用c函数来进行的了,一不做二不休,继续修改优化,代码我就不在继续贴了,附件中有包含了自动测试的整个项目文件,优化后,最终的效果如下:

    2011-12-31 14:29:08.520 otest[87180:903] [<span style="color: #2c2cfb;">0.915</span>] 使用subpathsAtPath然后循环调用NSFileManager获取目录总大小
    2011-12-31 14:29:08.860 otest[87180:903] [<span style="color: #2c2cfb;">0.339</span>] 使用subpathsAtPath然后循环调用unix c函数获取目录总大小
    2011-12-31 14:29:08.953 otest[87180:903] [<span style="color: #2c2cfb;">0.092</span>] 使用纯unix c递归
  • 相关阅读:
    模拟赛总结
    2018.04.06学习总结
    2018.04.06学习总结
    Java实现 LeetCode 672 灯泡开关 Ⅱ(数学思路问题)
    Java实现 LeetCode 671 二叉树中第二小的节点(遍历树)
    Java实现 LeetCode 671 二叉树中第二小的节点(遍历树)
    Java实现 LeetCode 671 二叉树中第二小的节点(遍历树)
    Java实现 LeetCode 670 最大交换(暴力)
    Java实现 LeetCode 670 最大交换(暴力)
    Java实现 LeetCode 670 最大交换(暴力)
  • 原文地址:https://www.cnblogs.com/appwgh/p/2517455.html
Copyright © 2011-2022 走看看