C++ recursive_directory_iterator miss some files

做~自己de王妃 提交于 2021-02-07 10:48:15

问题


I'm trying to get all files in directory through c++17 on my visual studio 2017 but I've just encountered a really weird problem. If I specify directory like this I can get all files without any problem:

    for (auto& p : std::filesystem::recursive_directory_iterator("C:\\Users\\r00t\\AppData\\Roaming\\Mozilla")) {
    if (std::filesystem::is_regular_file(p.path())) {
            std::cout << p.path() << std::endl;
        }
}

But I need all file list on APPDATA, and I'm trying to get path with getenv() function and when using it "recursive_directory_iterator" function skipping files:

    for (auto& p : std::filesystem::recursive_directory_iterator(getenv("APPDATA"))) {
    if (std::filesystem::is_regular_file(p.path())) {
            std::cout << p.path() << std::endl;
        }
}

Is that because of using getenv() function? Some folders that skipping when using getenv;

Mozilla 
TeamWiever
NVIDIA  

and so on ..

Btw, I'm using C++ last 5 days and definitely don't have any clue what causes for that behavior. Please help me, right now I'm stuck.

EDIT :

    for (auto& p : std::filesystem::directory_iterator(getenv("APPDATA"))) {
    std::string targetFolder = p.path().string();
    for (auto& targetFolderFiles : std::filesystem::recursive_directory_iterator(targetFolder)) {
        if (std::filesystem::is_regular_file(targetFolderFiles.path())) {
            std::cout << targetFolderFiles.path() << std::endl;
        }
    }
}

This is also not working, seems like i must put string into function like this:

recursive_directory_iterator("C:\\Users\\r00t\\AppData\\Roaming\\Mozilla")

otherwise definitely not working, LOL ??


EDIT - PROBLEM FIXED

Using experimental library is working with C++14 compiler like as expected.

#include <experimental/filesystem>

Now i can able to get all files without problem.Seems like this is problem about C++17 and filesystem library .. Thanks for all support guys.


回答1:


getenv() returns a char* or NULL. <filesystem> is probably operating with wchar_t* strings since you are on Windows. Use SHGetKnownFolderPath(...) to query for where special folders are.

What happens when you run your program is probably that you hit some character that can't be displayed with your current locale ("C" if not set explicitly) so it sets your outstream in fail mode. You can however set your locale to UTF-16LE to remedy this. It works with /std:c++17 and the standard <filesystem> header:

#include <Shlobj.h> // SHGetKnownFolderPath
#include <clocale>  // std::setlocale 
#include <io.h>     // _setmode
#include <fcntl.h>  // _O_U16TEXT

Code Page Identifiers

const char CP_UTF_16LE[] = ".1200";
setlocale(LC_ALL, CP_UTF_16LE);

_setmode

_setmode(_fileno(stdout), _O_U16TEXT);

With that in place, the path you get from SHGetKnownFolderPath should work:

PWSTR the_path;
if(SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, NULL, &the_path) == S_OK) {
    for(auto& p : std::filesystem::recursive_directory_iterator(the_path)) {
        std::wcout << p.path() << L"\n";

        // you can also detect if the outstream is in fail mode: 
        if (std::wcout.fail()) {
            std::wcout.clear();  // ... and clear the fail mode
            std::wcout << L" (wcout was fail mode)\n";
        }
    }
    CoTaskMemFree(the_path);
}

You may also find the list of Default Known Folders in Windows useful.



来源:https://stackoverflow.com/questions/53821593/c-recursive-directory-iterator-miss-some-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!