Hi,

I was wondering if anyone has encountered this problem. I'm using Win32 API calls FirstFile() and FindNextFile() to search for files on my computer. The problem is, both function calls seem to return extra files that aren't part of my search string. Has anyone else experienced the same problem?

I wrote a C/C++ console program that prompts for a Search String and a Search Path.

To recreate this problem, I enter "bc" as the search string (without the quotes) then enter the search path as "C:\" .. again, without the quotes but the backslash is required.

The program will start by gathering all directories and subdirectories that exist on the computer then search for files in each directory that contain the search string by passing C:\*bc* to FindFirstFile(). The program attaches the asterisks at the beginning and end of the Search String.

FindFirstFile and FindNextFile returns many files that contain the letters "bc", "bC", "Bc", and "BC". The problem is, these function calls will also return a few files that don't contain the letter "bc","BC","bC", or "Bc".

I've attached the source code.

If you'd like to run this code to see what I'm jabbering about, just be aware that it generates a file called findfile.dat. I use this file as an aid to debugging and contains the list of all files found. For files where there is an incorrect match, I print BAD MATCH.... It flags a BAD MATCH for files that contain "BC","bC", or "Bc" so ignore those. But it will also flag a BAD MATCH for files that don't contain these letters and also indicate which function call found that file, either FindFirstFile() or FindNextFile().


bronzefury

Attachments
/*
  Name: 
  Copyright: 
  Author: 
  Date: 21/05/05 22:24
  Description: 
*/
#include <windows.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include "FileFinder.hpp"

/*************************************************
-- Constructors/Destructors
**************************************************/

FileFinder::FileFinder(const TCHARptr filename)
{
   directoryIndex = 0;
   readpointer = 0;
   writepointer = 0;
   numberOfFilesFound = 0;
   i = 0;
   allFilesFoundIndex = 0;
   
    filesFound.open("findfile.dat");
    if (filesFound.fail())
    {
       std::cout << "Unable to create file findfile.dat" << std::endl;
       system("PAUSE");
    }
       
   strncpy(Filename,filename,MAX_PATH);
   
   // if search path not specified, use current directory ".\"
   strncpy(StartingDirectory,".\\",MAX_PATH);
}

FileFinder::FileFinder(const TCHARptr filename,const TCHARptr startingDirectory)
{
   directoryIndex = 0;
   readpointer = 0;
   writepointer = 0;

   numberOfFilesFound = 0;
   i = 0;
   allFilesFoundIndex = 0;
   
    filesFound.open("findfile.dat");
    if (filesFound.fail())
    {
       std::cout << "Unable to create file findfile.dat" << std::endl;
       system("PAUSE");
       //return false;
    }
 
   strncpy(Filename,filename,MAX_PATH);
   strncpy(StartingDirectory,startingDirectory,MAX_PATH);

}


FileFinder::~FileFinder()
{
   delete [] allFilesFound;
}


/*************************************************
-- Public Class Methods
**************************************************/

directory& FileFinder::getListOfFilesFound(const int index)
{
    return allFilesFound[index];
}

int FileFinder::getNumberOfFilesFound()
{
    return numberOfFilesFound;
}

void FileFinder::setSearchString(const TCHARptr filename)
{
     strncpy(Filename,filename,MAX_PATH);
}

void FileFinder::setSearchPath(const TCHARptr startingDirectory)
{
     strncpy(StartingDirectory,startingDirectory,MAX_PATH);
}

int FileFinder::findFiles()
{
    directoryIndex = 0;
    readpointer = 0;
    writepointer = 0;
    numberOfFilesFound = 0;
    i = 0;
    allFilesFoundIndex = 0;
    char *s;
       
    std::cout << "Searching for " << Filename << " at path " << StartingDirectory << std::endl;
    
    // dynamic array of type directory
    directory* directoryArray = new directory[BUFFER_SIZE];
    strncpy(directoryArray[writepointer].path,StartingDirectory,MAX_PATH);
    writepointer = writepointer + 1;

    allFilesFound = new directory[MAX_FILES_FOUND];

    // get list of all directories and subdirectories
    while ((readpointer < writepointer) && (writepointer < BUFFER_SIZE)) {
        strncpy(directoryAndFilename,directoryArray[readpointer].path,MAX_PATH);
        strncpy(currentdir,directoryArray[readpointer].path,MAX_PATH);
        strncat(directoryAndFilename,"*",1);// add wildcard

        readpointer = readpointer + 1;
        hFile = FindFirstFile (directoryAndFilename, &lpffd);
        if (hFile == INVALID_HANDLE_VALUE) {
           // do nothing
        }
        else {
           if (
                  ((lpffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
                  &&
                  ((strcmp(lpffd.cFileName,".")))
                 ) {

                 if ((writepointer) >= BUFFER_SIZE) {
                    // stop adding to directoryArray
                    // and don't increment writepointer anymore
                    // because we've hit the limit
                 }
                 else {
                    strncpy(directoryArray[writepointer].path,currentdir,MAX_PATH);
                    strncat(directoryArray[writepointer].path,lpffd.cFileName,MAX_PATH);
                    strncat(directoryArray[writepointer].path,"\\",1);// append "\"    
                    writepointer = writepointer + 1;
                 }
    
            }
             
            while ( (FindNextFile(hFile, &lpffd))) {
                if (((lpffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
                     &&
                     ((strcmp(lpffd.cFileName,"..")))
                   ) {
                    if ((writepointer) >= BUFFER_SIZE) {
                       // stop adding to directoryArray
                       // and don't increment writepointer anymore
                       // because we've hit the limit
                    }
                    else {
                       strncpy(directoryArray[writepointer].path,currentdir,MAX_PATH);
                       strncat(directoryArray[writepointer].path,lpffd.cFileName,MAX_PATH);
                       strncat(directoryArray[writepointer].path,"\\",1);// append "\"    
                       writepointer = writepointer + 1;
                    }    

                } // if
             } // while
             FindClose(hFile);
        }
    } // while (readpointer != writepointer

    directoryIndex = writepointer;

    // now find all the files             
    for (i = 0; i < directoryIndex; i=i+1) {

//        directoryAndFilename[0] = '\0';
        strncpy(currentdir,directoryArray[i].path,MAX_PATH);
                
        strncpy(directoryAndFilename,directoryArray[i].path,MAX_PATH);

        strncat(directoryAndFilename,"*",1);
        strncat(directoryAndFilename,Filename,MAX_PATH);
        strncat(directoryAndFilename,"*",1);
        
        strncpy(lpffd.cFileName,"\0",1);

        hFile = FindFirstFile (directoryAndFilename, &lpffd);

        if (hFile == INVALID_HANDLE_VALUE) {
           // do nothing
        }
        else {
             if (
                   (lpffd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
                ) {
                // do nothing
             } 
             else {

                //workaround: used this to filter out extra files
                //that FindFirstFile returns
                s = strstr(lpffd.cFileName,Filename);

                if (s == 0) {
                          std::cout << "BAD MATCH FindFirstFile - Extra File::" << lpffd.cFileName << std::endl;             
                          filesFound << "BAD MATCH FindFirstFile - Extra File::" << i << " " << currentdir << lpffd.cFileName << std::endl;
                }
                if (allFilesFoundIndex < MAX_FILES_FOUND) {
                   //s != 0 is a workaround to filter out extra files
                   //return by FindFirstFile
                   //if (s != 0) {
                      filesFound << currentdir << lpffd.cFileName  << std::endl;
                      strncpy(allFilesFound[allFilesFoundIndex].path,currentdir,MAX_PATH);
                      strncat(allFilesFound[allFilesFoundIndex].path,lpffd.cFileName,MAX_PATH);
                      allFilesFoundIndex = allFilesFoundIndex + 1;
                      numberOfFilesFound = numberOfFilesFound + 1;
                   //}
                }
             }
             
             // keep reading directory contents up to last file
             // or directory

             while (FindNextFile(hFile, &lpffd)) {
              
                if  (
                       (lpffd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
                    )
                {
                   // do nothing
                }
                else {


                    //workaround: used this to filter out extra files
                    //that FindFirstFile returns
                    s = strstr(lpffd.cFileName,Filename);

                    if (s == 0) {
                          //std::cout << "strstr=" << strstr(lpffd.cFileName,"bc") << std::endl;
                          std::cout << "BAD MATCH FindNextFile - Extra File::" << lpffd.cFileName << std::endl;             
                          filesFound << "BAD MATCH FindNextFile - Extra File::" << i << " " << currentdir << lpffd.cFileName << std::endl;
                          //system("PAUSE");
                       }

                   if (allFilesFoundIndex < MAX_FILES_FOUND) {
                      //s != 0 is a workaround used this to filter out extra files
                      //that FindFirstFile returns
                      //if (s != 0) {
                         filesFound << currentdir << lpffd.cFileName  << std::endl;
                         strncpy(allFilesFound[allFilesFoundIndex].path,currentdir,MAX_PATH);
                         strncat(allFilesFound[allFilesFoundIndex].path,lpffd.cFileName,MAX_PATH);
                         allFilesFoundIndex = allFilesFoundIndex + 1;                   
                         numberOfFilesFound = numberOfFilesFound + 1;
                      //} // s != 0
                   }
                }

             }// while
             
             FindClose(hFile);

        } // else


    } // for loop directoryIndex > 0
    delete [] directoryArray;
    
    return (numberOfFilesFound);

           
}
/*
  Name: 
  Copyright: 
  Author: 
  Date: 21/05/05 22:23
  Description: 
*/

#ifndef FILEFINDER_HPP
#define FILEFINDER_HPP

#include <windows.h>
#include <cstdlib>
#include <iostream>
#include <fstream>

typedef TCHAR* TCHARptr;

struct directory {
       char path[MAX_PATH+1];
};

const int BUFFER_SIZE = 32768;
const int MAX_FILES_FOUND = 32768;

class FileFinder      
{
 public:
    // constructors
    FileFinder(const TCHARptr filename);
    FileFinder(const TCHARptr filename,const TCHARptr startingDirectory);    

    // destructor
    ~FileFinder();
        
    // methods    
    int findFiles();
    int getNumberOfFilesFound();
    void FileFinder::setSearchString(const TCHARptr filename);
    void FileFinder::setSearchPath(const TCHARptr startingDirectory);

    directory& FileFinder::getListOfFilesFound(const int index);
    
 private:
   
    int directoryIndex;
    int readpointer;
    int writepointer;
    int numberOfFilesFound;
    int i;
    int allFilesFoundIndex;
    
    HANDLE hFile;
    
    TCHAR Filename[MAX_PATH+1];
    TCHAR StartingDirectory[MAX_PATH+1];
    TCHAR directoryAndFilename[MAX_PATH+1];
    TCHAR currentdir[MAX_PATH+1];
    
    WIN32_FIND_DATA lpffd;
    
    std::ofstream filesFound;
    
    directory* allFilesFound;
};

#endif // FILEFINDER_HPP
#include <windows.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include "FileFinder.hpp"

using namespace std;

int main(int argc, char *argv[])
{
    int numberOfFilesFound = 0;
    char filename[MAX_PATH] = "";
    char path[MAX_PATH] = "";
    directory listOfFiles;
    char filefound[MAX_PATH] = "";
    int i = 0;

    
    FileFinder a("abc.txt","C:\\");

    cout << "Enter search string:" << endl;
    cin.getline(filename,40);
    
    cout << "Enter search path:" << endl;
    // enter backslash(\) after directory name
    // for example, to search for files starting
    // at C: enter C:\ at the console prompt
    cin.getline(path,40);
    
    a.setSearchString(filename);
    a.setSearchPath(path);
    
    numberOfFilesFound = a.findFiles();
    
    cout << "main::found " << numberOfFilesFound << " file(s)" << endl;

    for (i = 0; i < a.getNumberOfFilesFound(); i++) {
       listOfFiles = a.getListOfFilesFound(i);
       strcpy(filefound,listOfFiles.path);
       cout << "index " << i << " filefound = " << filefound << endl;
    }
    
    system("PAUSE");
    return EXIT_SUCCESS;
}
This article has been dead for over six months. Start a new discussion instead.