代码之家  ›  专栏  ›  技术社区  ›  Peter Parker

在C++中爬行递归NTFS目录的最快方法

  •  6
  • Peter Parker  · 技术社区  · 14 年前

    我已经写了一个小爬虫扫描和度假目录结构。

    它基于dirent(这是FindNextFileA的一个小包装器)

    约123473ms可存储4500个文件(thinkpad t60p本地三星320 GB 2.5英寸高清)。 123473毫秒内找到121481个文件 这个速度正常吗?

    这是我的密码:

    int testPrintDir(std::string  strDir, std::string strPattern="*", bool recurse=true){
      struct dirent *ent;
      DIR *dir;
      dir = opendir (strDir.c_str());
      int retVal = 0;
      if (dir != NULL) {
        while ((ent = readdir (dir)) != NULL) {
          if (strcmp(ent->d_name, ".") !=0 &&  strcmp(ent->d_name, "..") !=0){
            std::string strFullName = strDir +"\\"+std::string(ent->d_name);
            std::string strType = "N/A";
            bool isDir = (ent->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0;
            strType = (isDir)?"DIR":"FILE";                 
            if ((!isDir)){
                 //printf ("%s <%s>\n", strFullName.c_str(),strType.c_str());//ent->d_name);
              retVal++;
            }   
            if (isDir && recurse){
                 retVal += testPrintDir(strFullName, strPattern, recurse);
            }
          }
        }
        closedir (dir);
        return retVal;
      } else {
        /* could not open directory */
        perror ("DIR NOT FOUND!");
        return -1;
      }
    }
    
    4 回复  |  直到 14 年前
        1
  •  5
  •   Billy ONeal IS4    10 年前

    在某些情况下,这样的速度是正常的。首先,使用FindFirstFileA而不是FindFirstFileW将导致从UTF-16转换为ANSI的开销。第二,如果您正在浏览操作系统尚未访问的目录,则至少会发生一次seek惩罚(对于大多数消费类硬盘驱动器,大约为16ms),将枚举限制在每秒100次目录检查以下。如果给定驱动器上的主文件表碎片严重,情况会变得更糟。

    关于文件数量,它更多地取决于每个目录的文件数量,而不是文件本身的数量。

        2
  •  3
  •   MSN    14 年前

    当您第一次执行递归目录爬网时,您可能应该首先枚举整个当前目录,并将完成后要访问的所有目录排队。这样,您就可以利用NTFS可能进行的任何即时预读优化。

    在随后的递归目录爬网中,如果目录的元数据适合系统缓存,则不管您如何操作。

        3
  •  2
  •   adf88    14 年前

    可能驱动器是瓶颈。但你可以试试:

    1. 字符串操作可以优化-使用std::String的字符数组instad。
    2. 不要通过值传递strPattern!
    3. 在调试之前不要创建strType
    4. 其他人建议在深入递归之前建立一个要处理的目录列表。要构建它,我建议使用单个静态数组(类似于2)或使用堆栈( alloca
    5. 文件系统使用Unicode来存储文件名?如果是,则使用unicode字符串 FindFirstFileW FindNextFileW 可能快一点。
        4
  •  0
  •   John    14 年前

    在递归潜水过程中,您保持DIR句柄打开。相反,保留一个您遇到的目录的本地列表,并在循环之外处理它们 closedir() .