2012-02-01 76 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; 
}