如何使用Windows API列出目录中的文件?

Joh*_*bia 9 c++ windows winapi directory-listing

我有这个代码,它显示目录本身的文件夹,而不是其内容.我想显示它的内容.我不想使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

semester2
Run Code Online (Sandbox Code Playgroud)

Har*_*ton 13

HANDLE hFind = FindFirstFile("C:\\semester2", &data);       // DIRECTORY
Run Code Online (Sandbox Code Playgroud)

你得到了这个目录,因为那就是你要求的.如果您需要这些文件,请询问:

HANDLE hFind = FindFirstFile("C:\\semester2\\*", &data);  // FILES
Run Code Online (Sandbox Code Playgroud)

(*.*如果你愿意,你可以改用它,但显然这只能起作用,因为它具有向后兼容性,所以应该避免使用.请参阅注释和RbMm的答案.)

  • `*.*`只是对DOS的回归.我认为更清楚地使用`*`代替. (2认同)

RbM*_*bMm 6

让我带的一些笔记"*.*"VS "*".这些报送者不相等.

我们的文件夹中可以存在2个不同的文件:somefilesomefile..

如果我们使用的低级别的API ZwQueryDirectoryFile"*.*"作为搜索表达式(这是第十个参数- FileName [in, optional])-我们会得到somefile.唯一的.但是,如果我们使用,"*"我们将获得两个文件 - somefilesomefile.

如果我们尝试,FindFirstFile("C:\\semester2\\*.*", &data);我们可以注意到两个文件somefilesomefile. 返回.所以这里"*.*"vs "*"具有相同的效果 - 使用没有区别.

为什么会这样?因为在FindFirstFileExin kernelbase(kernel32)内部"*.*"会对mask 进行特殊检查,如果为true,则替换为""(具有相同效果的空名称"*").

我认为这样做是为了在用户通过"*.*"而不是正确的"*"以及与遗留代码的向后兼容性时修复一个非常常见的错误.

.并且..它实际上不是目录的一部分,因为它存储在磁盘上,但是由Win32 API添加.

这不是真的.

  • for- FATstyle文件系统这实际上存储在FAT目录中作为第一个条目.
  • NTFS没有这样的条目,但NTFS.sys如果他们在掩码中人为地添加这两个条目.

所以这不是在Win32 API级别,而是在内核 - 驱动程序级别.

总而言之,"*.*"现在使用Win32 API可以正常工作 - 但是正确和干净的方法是在"*"这里使用.
"*.*"ZwQueryDirectoryFileapi 错误.

  • @HarryJohnston - 请原谅我在这里提到了 NT api。对于 99% 以上的用户模式程序员来说,这似乎是下流的脏话。但这里仅用于显示系统在哪个级别对“*.*”进行黑客攻击。关于NT api我有另一种观点(我认为它不会进行这样的黑客攻击是正确的),我喜欢它直接返回错误代码(不转换它而失去准确性),严格统一的签名(比较win32),很多与 win32 相比,它更强大、更有效,因为 win32 中根本不存在这种可能性..但这一切都已经是题外话了。我不建议任何人使用这个:) (3认同)
  • 如果我指出这是人们建议不要使用本机API的原因之一,希望您能原谅我。:-) (2认同)