Ошибка в листинге файла из каталога в C ++ - PullRequest
1 голос
/ 01 марта 2011

У меня проблема с моим кодом. Всякий раз, когда я запускаю программу, последний поиск файла будет возвращать нулевое значение там, где его не должно быть.

вот код:

#include <vector>
#include <string>
#include <windows.h>
#include <stdio.h>
#include <iostream> 
#include <conio.h>

using namespace std;

string GetPath(string path){
        char directory[1024];
        vector <string> filelist;
        strcpy_s(directory,path.c_str());
        BOOL checker;

            WIN32_FIND_DATA findFileData;
            HANDLE hFind = FindFirstFile((LPCSTR)directory, &findFileData);
            cout <<"Files in:" <<"\n"<<directory<<"\n"<<endl;
            checker = FindNextFile(hFind, &findFileData);

            while(checker)
            {
                checker = FindNextFile(hFind, &findFileData);
                filelist.push_back(findFileData.cFileName);//save file list in vector
                cout << findFileData.cFileName << endl;
            }

            DWORD error = GetLastError();
            if( error != ERROR_NO_MORE_FILES)
            {

            }
            /*for (unsigned i=1;i<filelist.size();i++){
                cout << filelist[i]<<endl;//print out the vector
            }*/


            return 0;
}

int main()
{
   string path;
   path="C:\\Program Files\\*.*";
   vector <string> handler;
   path = GetPath(path);
}

Ответы [ 5 ]

1 голос
/ 01 марта 2011

Попробуйте это как проверку работоспособности:

#include <tchar.h>
#include <stdexcept>
#include <vector>
#include <string>
#include <iostream>
#include <windows.h>

#ifdef UNICODE
typedef std::wstring tstring;
static std::wostream& tcout = std::wcout;
#else
typedef std::string tstring;
static std::ostream& tcout = std::cout;
#endif

std::vector<tstring> GetPath(tstring const& path)
{
    WIN32_FIND_DATA findFileData;
    HANDLE const hFind = FindFirstFile(path.c_str(), &findFileData);
    if (hFind == INVALID_HANDLE_VALUE)
        throw std::runtime_error(""); // realistically, throw something useful

    std::vector<tstring> filelist;
    do filelist.push_back(findFileData.cFileName);
    while (FindNextFile(hFind, &findFileData));
    FindClose(hFind);
    if (GetLastError() != ERROR_NO_MORE_FILES)
        throw std::runtime_error(""); // realistically, throw something useful
    return filelist;
}

int _tmain()
{
    std::vector<tstring> files = GetPath(_T("C:\\Program Files\\*.*"));
    for (std::vector<tstring>::const_iterator iter = files.begin(), iter_end = files.end(); iter != iter_end; ++iter)
        tcout << *iter << _T('\n');
}

Если это работает, очистите логику обработки ошибок и используйте ее; -].Если это не так, то @young был прав, и у вас есть проблемы с локализацией;измените настройки своего проекта, чтобы использовать Юникод в качестве набора символов, и он должен работать.

1 голос
/ 01 марта 2011

Хорошо, я заметил одну вещь: ваша функция GetPath возвращает строку.В конце вы делаете: вернуть 0;Это вызовет строковый конструктор, который принимает char * в качестве параметра и попытается создать строку с нулевым указателем.Я предполагаю, что это приведет к сбою в большинстве реализаций STl: -).

В связи с вашей проблемой вы можете попробовать это:

#include <Strsafe.h>

//from MSDN
void 
DisplayError(LPTSTR lpszFunction) 
{ 
    // Retrieve the system error message for the last-error code
    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError(); 

    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                   FORMAT_MESSAGE_FROM_SYSTEM |
                   FORMAT_MESSAGE_IGNORE_INSERTS,
                   NULL,
                   dw,
                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                   (LPTSTR) &lpMsgBuf,
                   0, 
                   NULL );

    // Display the error message and exit the process

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); 

    StringCchPrintf((LPTSTR)lpDisplayBuf, 
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"), 
        lpszFunction, dw, lpMsgBuf); 

    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); 

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
}

void 
GetPath(string path)
{
    vector <string> filelist;

    WIN32_FIND_DATA findFileData;
    HANDLE hFind = FindFirstFile(path.c_str(), &findFileData);

    if (hFind == INVALID_HANDLE_VALUE) 
    {
        DisplayError("FindFirstFile");
        return;
    } 

    cout <<"Enumerating files in: " <<"\n"<< path << "\n" << endl;

    while( FindNextFile(hFind, &findFileData) != 0 )
    {
        filelist.push_back( findFileData.cFileName );//save file list in vector
    }

    if (  ERROR_NO_MORE_FILES != GetLastError() )
    {
        DisplayError("FindFirstFile");
    }

    FindClose(hFind);

    unsigned int listSize = filelist.size();

    cout << "List Count: " << listSize << "\n";

    for (unsigned i=0; i  < listSize; ++i)
    {
        cout << filelist[i] << "\n";//print out the vector
    }

    cout << "\nListing complete\n" << endl;
}

int main()
{
    string path;
    path="C:\\Program Files\\*.*";
    GetPath(path);
}

И сообщите нам, какой код ошибки вы получаетепосле завершения цикла while.

1 голос
/ 01 марта 2011

Мне кажется, что вам не следует вызывать FindNextFile внутри цикла: я полагаю, что если вы внимательно посмотрите на вывод, вы заметите, что каждый второй файл отсутствует в вашем списке.

Это связано с тем, что вызов FindNextFile в состоянии while загружает следующую деталь файла в FindFileData. Затем следующая строка кода (внутри цикла while) снова выполняет этот процесс, перезаписывая первое совпадение вторым. Таким образом, вы получаете только каждую вторую запись.

Для четного числа файлов вы также получите сложность, которую вы описали в конце.

1 голос
/ 01 марта 2011

Во-первых, вам нужно проверить hFind, возвращаемое из FindFirstFile (), поскольку оно может возвращать INVALID_HANDLE_VALUE.

Во-вторых, ваш цикл while должен выглядеть следующим образом

while(FindNextFile(hFind, &findFileData)!= 0)
{
    filelist.push_back(findFileData.cFileName);//save file list in vector
}

DWORD error = GetLastError();
if( error != ERROR_NO_MORE_FILES)
{
    // You are not expecting this error so you might want to do something here.
}
0 голосов
/ 01 марта 2011

Это мой ответ

#include <vector>
#include <string>
#include <windows.h>
#include <stdio.h>
#include <iostream> 
#include <conio.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <time.h>
#include <exception>
#include <WinBase.h>
#include <tchar.h>
#include <strsafe.h>
#include <algorithm>

        using namespace std;
int ifException(string directory) throw()
    {
        DWORD returnvalue;
        returnvalue = GetFileAttributes(directory.c_str());
            if(returnvalue == ((DWORD)-1))
            {
                return 0;
            }
            else
            {   
                return 1;
            }
}
string FileTime(string filename, string path){

    char timeStr[ 100 ] = "";
    char fpath[9999];
    string buffer;

                replace (path.begin(),path.end(),'*','\0');
                replace (path.begin(),path.end(),'.','\0');
                strcpy_s(fpath,path.c_str());
                path = filename;
            struct stat buf;
            string filepath;
            filepath = fpath;
            filepath += filename;
            //cout << filepath << endl;
            strcpy_s(fpath,filepath.c_str());
            if (!stat(fpath, &buf))
            {
                strftime(timeStr, 100, "%d-%m-%Y %H:%M:%S", localtime(&buf.st_mtime));
            }
            buffer = filename;
            buffer += "\t\t";
            buffer +=timeStr;
            return buffer;
}


vector <string> GetPath(string path)
    {
            char directory[9999];
            vector <string> filelist;
            string buffer;
            strcpy_s(directory,path.c_str());
            BOOL checker;
                WIN32_FIND_DATA findFileData;
                HANDLE hFind = FindFirstFile((LPCSTR)directory, &findFileData);


                try
                    {
                        ifException(directory);

                    }catch(int i)
                    {   
                        if (i==0)
                        {
                            _getch();
                            exit(1);
                        }
                    }
                buffer = findFileData.cFileName;
                filelist.push_back(buffer);
                checker = FindNextFile(hFind, &findFileData);
                while(checker)
                {
                    checker = FindNextFile(hFind, &findFileData);
                        buffer = findFileData.cFileName;
                        buffer = FileTime(buffer,path);
                    filelist.push_back(buffer);//save file list in vector
                    if(checker == 0)
                    {
                        filelist.resize(filelist.size());
                        return filelist;
                    }
                }
    return filelist;
    }

    int main()
    {
       string path;

       path="C:\\Documents and Settings\\OJT\\My Documents\\*.*";// the directory
       vector <string> handler;
       handler = GetPath(path);
        for (unsigned i=1;i<handler.size()-1;i++)
        {
            cout << handler[i]<<endl;//print out the vector
        }
       _getch();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...