简体   繁体   中英

List all text files in directory in C++

I am trying to store the name of all txt files in a directory in a string and print them out. I need to count the number of txt files in the directory and then print the names. The part of counting is working, but I can't seem to get the name working. I have found some examples but they don't work in visual studio which is what I'm using.

Here is my code.

int main() {

    bool x = true;
    int i = 0;

    wchar_t* file = L"../Menu/Circuitos/*.txt";
    WIN32_FIND_DATA FindFileData;

    HANDLE hFind;

    hFind = FindFirstFile(file, &FindFileData);

    if (hFind != INVALID_HANDLE_VALUE) {

        i++;

        while ((x = FindNextFile(hFind, &FindFileData)) == TRUE) {
            i++;
        }
    }

    cout << "number of files " << i << endl;

    return 0;
}

FindFirstFile already has the first valid handle. If you immediately call FindNextFile then the first handle is lost. The file count in your example would be wrong.

Use do-while loop istead.

Also, the handle obtained from FindFirstFile must be closed with FindClose

HANDLE hFind;
hFind = FindFirstFile(file, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE) 
{
    do {
        wcout << FindFileData.cFileName << "\n";
        i++;
    } while (FindNextFile(hFind, &FindFileData));
    FindClose(hFind);
}
cout << "number of files " << i << endl;

Use std::vector and std::wstring to store the items

#include <string>
#include <vector>

...
std::vector<std::wstring> vs;
HANDLE hFind;
hFind = FindFirstFile(file, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE) 
{
    do {
        vs.push_back(FindFileData.cFileName);
    } while (FindNextFile(hFind, &FindFileData));
    FindClose(hFind);
}

std::cout << "count:" << vs.size() << "\n";
for (auto item : vs)
    std::wcout << item << "\n";

For some older compilers auto may not be available, use this instead

for (int i = 0; i < vs.size(); i++)
    std::wcout << vs[i] << "\n";

Note, Windows API works with c-strings. In many cases you have to use .c_str() to obtain character array. For example:

if (vs.size())
{
    std::wstring str = vs[0];
    MessageBox(0, str.c_str(), 0, 0);
}

Here is a portable version using the new ISO Standard Filesystem Library TS (technical specification) for those with compilers that support it:

#include <vector>
#include <iostream>
#include <algorithm>
#include <experimental/filesystem>

// for readability
namespace fs = std::experimental::filesystem;

/**
 * Function object to test directory entries
 * for a specific file extension.
 */
struct file_extension_is
{
    std::string ext;

    file_extension_is(std::string const& ext): ext(ext) {}

    bool operator()(fs::directory_entry const& entry) const
    {
        return entry.path().extension() == ext;
    }
};

int main(int, char* argv[])
{
    try
    {
        // directory supplied on the command line if present
        // else current directory
        fs::path dir = argv[1] ? argv[1] : ".";

        // place to store the results
        std::vector<fs::directory_entry> entries;

        // copy directory entries that have file extension ".txt"
        // to the results
        fs::directory_iterator di(dir);
        fs::directory_iterator end;

        std::copy_if(di, end, std::back_inserter(entries),
            file_extension_is(".txt"));

        // print it all out

        std::cout << "Number of files: " << entries.size() << '\n';

        for(auto const& entry: entries)
            std::cout << entry.path().string() << '\n';
    }
    catch(std::exception const& e)
    {
        std::cerr << e.what() << '\n';
    }
    catch(...)
    {
        std::cerr << "Unknown exception." << '\n';
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM