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递归
  • 相关阅读:
    Leetcode OJ: Rotate List
    Leetcode OJ: Reverse Words in a String
    Effective C++读书笔记
    word改变下划线与文字的距离
    sql 取出表中不重复的值
    Iso文件用utrliso怎么安装
    Spring注入aspectJ切面
    Spring中利用java注解声明切面
    Spring面向切面编程
    spring中部分异常
  • 原文地址:https://www.cnblogs.com/appwgh/p/2517455.html
Copyright © 2011-2022 走看看