我有这个代码,它显示了目录本身的文件夹,而不是其内容。我想显示它的内容。我不想使用boost :: filesystem。
我该如何解决这个问题?
代码:
#include <windows.h>
#include <iostream>
int main()
{
WIN32_FIND_DATA data;
HANDLE hFind = FindFirstFile("C:\\semester2", &data); // DIRECTORY
if ( hFind != INVALID_HANDLE_VALUE ) {
do {
std::cout << data.cFileName << std::endl;
} while (FindNextFile(hFind, &data));
FindClose(hFind);
}
}
输出:
semester2
答案 0 :(得分:13)
HANDLE hFind = FindFirstFile("C:\\semester2", &data); // DIRECTORY
你有这个目录,因为那就是你要求的。如果你想要这些文件,请询问:
HANDLE hFind = FindFirstFile("C:\\semester2\\*", &data); // FILES
(如果您愿意,可以使用*.*
,但显然这只是因为向后兼容性黑客而有效,所以应该避免。请参阅评论和RbMm的答案。)
答案 1 :(得分:6)
让我对"*.*"
vs "*"
做一些说明。这些报送者不相等。
我们的文件夹中可以存在2个不同的文件:somefile
和somefile.
。
如果我们使用低级别的api ZwQueryDirectoryFile
和"*.*"
作为搜索表达式(这是第10个参数 - FileName [in, optional]
) - 我们会得到{仅限{1}}。但是,如果我们使用somefile.
,我们会同时获取这两个文件 - "*"
和somefile
如果我们尝试somefile.
,我们可以注意到,返回文件FindFirstFile("C:\\semester2\\*.*", &data);
和somefile
。因此somefile.
vs "*.*"
具有相同的效果 - 使用方式没有差异。
为什么会这样?因为"*"
(FindFirstFileEx
)中的kernelbase
内部会对kernel32
掩码进行特殊检查,如果为真,则替换为"*.*"
(具有相同名称的空名称)效果为""
)。
我认为这样可以解决用户通过"*"
而不是正确的"*.*"
时出现的非常常见的错误,以及与遗留代码的向后兼容性。
"*"
和.
实际上并不是目录的一部分,因为它存储在 磁盘,但是由Win32 API添加。
事实并非如此。
..
- 样式文件系统,它实际上存储在FAT目录中作为第一个条目。 FAT
中没有这样的条目,但NTFS
人工添加这两个条目(如果它们在掩码中)。 所以这不是在Win32 API级别,而是在内核 - 驱动程序级别。
总而言之,NTFS.sys
在Win32 API方面的工作正常至关重要 - 但正确而干净的方法是在此处使用"*.*"
。
"*"
api会错误"*.*"
。
答案 2 :(得分:1)
这是一个示例实现:
#include <iostream>
#include <vector>
#include <string>
#include <Windows.h>
std::vector<std::string>
list_directory(
const std::string &directory)
{
WIN32_FIND_DATAA findData;
HANDLE hFind = INVALID_HANDLE_VALUE;
std::string full_path = directory + "\\*";
std::vector<std::string> dir_list;
hFind = FindFirstFileA(full_path.c_str(), &findData);
if (hFind == INVALID_HANDLE_VALUE)
throw std::runtime_error("Invalid handle value! Please check your path...");
while (FindNextFileA(hFind, &findData) != 0)
{
dir_list.push_back(std::string(findData.cFileName));
}
FindClose(hFind);
return dir_list;
}
注意:如果您使用 C++ 11 或 std::filesystem 如果您使用 C++ 17,最好使用类似 boost::filesystem 的东西。 此外输入路径必须像 C:\path 而不是 C:\path\ 否则这将不起作用!!
答案 3 :(得分:0)
Harrys回答实际上会产生在所需文件夹"C:\\semester2"
中具有扩展名的文件和文件夹。
因此,例如,如果您有一个名为"C:\\semester2\\math.course"
的文件夹,则上面的示例也会找到它。此外,如果您有一个名为"C:\\semester2\\math_scores"
的文件(注意它没有扩展名),则无法找到它。
考虑到上述情况,我建议采用以下解决方案:
HANDLE hFind = FindFirstFile("C:\\semester2\\*", &data);
这将列出目录下的整个项目列表。 可以通过以下方式过滤目录:
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// directory
}
else
{
// file
}
以下内容可用于参考:FileAttributes constants,FIND_DATA struct,FindFirstFile API