首页 > 解决方案 > 使用 C++ 打印 C:\ 中的所有文件路径

问题描述

我试图打印 C: 中的所有文件路径。但是我看到我收到了权限错误。

void getAllFilesInDirectory(wstring directoryPath, vector<wstring> &files) {
    for (filesystem::directory_entry directory : filesystem::directory_iterator(directoryPath)) {


        if (GetFileAttributesW(directory.path().wstring().c_str()) == FILE_ATTRIBUTE_SYSTEM)
            continue;

        //Checking if directory.path is a file or a directory
        if (GetFileAttributesW(directory.path().wstring().c_str()) == FILE_ATTRIBUTE_NORMAL) {
            files.push_back(directory.path().wstring());
            wcout << "The path is " << directory.path().wstring() << endl;
            continue;
        }

        try {
            for (filesystem::directory_entry file : filesystem::recursive_directory_iterator(directory)) {


                if (GetFileAttributesW(file.path().wstring().c_str()) == FILE_ATTRIBUTE_DIRECTORY) {
                    continue;
                }


                wcout << "The path of the file is " << file.path().wstring() << endl;
                files.push_back(file.path().wstring());
            }
        } catch (exception &e) {
            wcout << "There is exception " << e.what() << " and the directory path is: " << directory.path().wstring()
                  << endl;

        }
    }
}

当我为函数提供一个常规目录(不是具有特权的目录)时,我的代码正在工作。

但是当我给他“C:\”时,他在打印了一点路径后退出了。

如果有人发布他在 C 驱动器中打印所有路径的方法,那就太好了。

谢谢!

标签: c++windowsvisual-studiofilesystems

解决方案


你在评论中说:

我希望我的代码会忽略他无权访问的文件

std::filesystem::directory_iterator并且std::filesystem::recursive_directory_iterator两者都有一个接受std::filesystem::directory_options枚举作为输入的构造函数,其中有一个skip_permission_denied可用于该目的的项目,例如:

void getAllFilesInDirectory(const wstring &directoryPath, vector<wstring> &files) {
    for (filesystem::directory_entry directory : filesystem::directory_iterator(directoryPath, filesystem::directory_options::skip_permission_denied)) {
        ...
        for (filesystem::directory_entry file : filesystem::recursive_directory_iterator(directory, filesystem::directory_options::skip_permission_denied)) {
            ...
        }
    }
}

附带说明一下,您可能需要考虑添加命名空间别名来缩短这些限定名称,例如:

namespace fs = std::filesystem;

for (fs::directory_entry directory : fs::directory_iterator(directoryPath, fs::directory_options::skip_permission_denied)) {
    ...
    for (fs::directory_entry file : fs::recursive_directory_iterator(directory, fs::directory_options::skip_permission_denied)) {
        ...
    }
}

另外,您的使用GetFileAttributesW()是错误的。您没有检查错误,也没有考虑到文件夹和文件可以(并且通常确实)分配了多个属性。&测试特定属性时使用(AND) 运算符。并且测试FILE_ATTRIBUTE_NORMAL属性并不是区分文件和文件夹的正确方法。FILE_ATTRIBUTE_DIRECTORY改为测试属性的存在/缺失。

试试这个:

namespace fs = std::filesystem;

void getAllFilesInDirectory(const wstring &directoryPath, vector<wstring> &files) {
    for (fs::directory_entry directory : fs::directory_iterator(directoryPath, fs::directory_options::skip_permission_denied)) {

        DWORD attrs = GetFileAttributesW(directory.path().wstring().c_str());

        if (attrs == INVALID_FILE_ATTRIBUTES) {
            DWORD err = GetLastError();
            wcerr << "Error " << err << " getting attributes for path " << directory.path().wstring() << endl;
            continue;
        }

        if (attrs & FILE_ATTRIBUTE_SYSTEM)
            continue;

        //Checking if directory.path is a file or a directory
        if (attrs & ~FILE_ATTRIBUTE_DIRECTORY) {
            files.push_back(directory.path().wstring());
            wcout << "The path is " << directory.path().wstring() << endl;
            continue;
        }

        try {
            for (fs::directory_entry file : fs::recursive_directory_iterator(directory, fs::directory_options::skip_permission_denied)) {

                attrs = GetFileAttributesW(file.path().wstring().c_str());

                if (attrs == INVALID_FILE_ATTRIBUTES) {
                    DWORD err = GetLastError();
                    wcerr << "Error " << err << " getting attributes for path " << file.path().wstring() << endl;
                    continue;
                }

                if (attrs & FILE_ATTRIBUTE_DIRECTORY)
                    continue;

                wcout << "The path of the file is " << file.path().wstring() << endl;
                files.push_back(file.path().wstring());
            }
        } catch (const exception &e) {
            wcout << "There is exception " << e.what() << " and the directory path is: " << directory.path().wstring() << endl;
        }
    }
}

推荐阅读