2012-02-01 99 views
0

什么是在Windows上搜索C++文件的最佳方式。我应该使用助推还是有更好的方法。我在构建文件系统库时遇到了一些问题。我发现这一点:文件搜索C++

#include <stdio.h> 
#include <dir.h> 
#include <string.h> 
#define ALL_ATTS (FA_DIREC | FA_ARCH) 

void walker(const char *, const char *); 

void walker(const char *path, const char *findme) 
{ 
struct ffblk finder; 
unsigned int res; 

chdir(path); 

for (res = findfirst("*.*", &finder, ALL_ATTS); res == 0; res = findnext(&finder)) 
{ 
if (strcmp(finder.ff_name, ".") == 0) continue; /* current dir */ 
if (strcmp(finder.ff_name, "..") == 0) continue; /* parent dir */ 

/* 
* If its a directory, examine it 
* else compare the filename with the one we're looking for 
*/ 
if (finder.ff_attrib & FA_DIREC) 
{ 
    char newpath[MAXPATH]; 
    strcpy(newpath, path); 
    strcat(newpath, "\\"); 
    strcat(newpath, finder.ff_name); 
    chdir(finder.ff_name); 
    walker(newpath, findme); 
    chdir(".."); 
    } 
    else 
    { 
    if (strcmp(finder.ff_name, findme) == 0) 
    { 
    printf("Found in: %s\n", path); 
    } 
    } 
    } 
    } 

    int main(void) 
    { 
    const char *root = "\\"; 
    char buf[BUFSIZ]; 

    printf ("This program will find a file on the current drive.\n" 
     "Enter the name of the file to look for: "); 

    fflush(stdout); 

    if (fgets(buf, sizeof(buf), stdin)) 
    { 
    strtok(buf, "\n"); /* Remove the newline character */ 
    walker(root, buf); 
    } 

    return(0); 
    } 

但没有DIR头的版本的作品...

+1

只有一个工作方式,但不工作,所以多路... – rodrigo 2012-02-01 20:28:00

+0

@rodrigo,没有得到你的意见(或它的相关性).. :( – Nim 2012-02-01 20:42:52

+0

我不会使用boost,除非你已经在你的项目中使用它,然而boost文件系统库是非常整洁的。 – Nim 2012-02-01 20:43:43

回答

0

我发现的boost ::文件系统工作得很好,只要你知道你在做什么。对我来说,以下工作:

#include <iostream> 
#include <string> 
#include "boost/filesystem.hpp" 
namespace fs = boost::filesystem; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    const std::string start = "C:\\"; 
    const std::string findme = "winsock.dll"; 

    fs::recursive_directory_iterator end; 
    fs::recursive_directory_iterator rdi(start); 

    while(rdi != end) 
    { 
     const std::string path = rdi->path().string(); 
     if(path.find(findme) != std::string::npos) 
     { 
      std::cout << path << std::endl; 
     } 

     try 
     { 
      ++rdi; // various system directories can bork this 
     } 
     catch(fs::filesystem_error e) 
     { 
      rdi.no_push(); // don't try to recurse into it 
      ++rdi; 
     } 
    } 

    return 0; 
} 
0

你可能要考虑的Win32 API,如FindFirstFileFindNextFile

有一些示例代码在MSDN上,如this

0

您可能想看看Matthew Wilson制作的recls库。

0

您发现的代码看起来像使用特定于某些特定“标准”库(甚至可能已经为MS-DOS编写)的函数。其次,它使用深度优先搜索;对于目录搜索,我通常更喜欢广度优先搜索。

我会尝试使用Windows桌面搜索和/或Windows搜索作为第一选择。如果用户启用了这些功能,它们将使用预先构建的索引来实现非常快的结果。

如果这是不可用的,我会使用代码的广度优先搜索,它看起来大致是这样的:

#include <windows.h> 
#include <queue> 
#include <sstream> 
#include <iostream> 
#include <algorithm> 

// I think MS's names for some things are obnoxious. 
const HANDLE HNULL = INVALID_HANDLE_VALUE; 
const int A_DIR = FILE_ATTRIBUTE_DIRECTORY; 

std::ostream &operator<<(std::ostream &os, FILETIME const &ft) { 
    SYSTEMTIME utc, lt; 
    FileTimeToSystemTime(&ft, &utc); 
    SystemTimeToTzSpecificLocalTime(NULL, &utc, &lt); 

    return os << lt.wHour << ":" << lt.wMinute << ":" << lt.wSecond << "." << lt.wMilliseconds; 
} 

void process(std::string const &path, WIN32_FIND_DATA const &file) { 
    std::cout << file.ftCreationTime << "\t" << path << file.cFileName << "\n"; 
} 

void find_file(std::string const &folder_name, std::string const &fmask) { 
    HANDLE finder;   // for FindFirstFile 
    WIN32_FIND_DATA file; // data about current file. 
    std::priority_queue<std::string, std::vector<std::string>, std::greater<std::string> > dirs; 
    dirs.push(folder_name); // start with passed directory 

    do { 
     std::string path = dirs.top();// retrieve directory to search 
     dirs.pop(); 

     if (path[path.size()-1] != '\\') // normalize the name. 
      path += "\\"; 

     std::string mask = path + fmask; // create mask for searching 

     // traverse a directory. 
     if (HNULL==(finder=FindFirstFile(mask.c_str(), &file))) { 
      continue; 
     } 
     do { 
      if (!(file.dwFileAttributes & A_DIR)) // print file names 
       process(path, file); 
     } while (FindNextFile(finder, &file)); 
     FindClose(finder); 
     if (HNULL==(finder=FindFirstFile((path + "*").c_str(), &file))) 
      continue; 
     do { 
      if ((file.dwFileAttributes & A_DIR) && (file.cFileName[0] != '.')) 
       dirs.push(path + file.cFileName); 
     } while (FindNextFile(finder, &file)); 
     FindClose(finder); 
    } while (!dirs.empty()); 
} 

int main(int argc, char **argv) { 
    if (argc > 2) 
     find_file(argv[1], argv[2]); 
    else 
     find_file("C:\\", "*"); 
    return 0; 
}