如何在Windows中使用FindNextFile调用来列出目录内容?
How to use FindNextFile call in Windows to list directory contents?
我有一小段代码,旨在使用Windows API列出目录的内容。
法典:
#include <iostream>
#include <Windows.h>
int wmain() {
WIN32_FIND_DATA data;
std::string dir = "c:\* ";
HANDLE hFind = FindFirstFileA(dir.c_str(), &data); // DIRECTORY
if (hFind != INVALID_HANDLE_VALUE) {
do {
std::cout << data.cFileName << std::endl;
} while (FindNextFileW(hFind, &data));
FindClose(hFind);
}
return 0;
}
错误:
Error C2664 'HANDLE FindFirstFileA(LPCSTR,LPWIN32_FIND_DATAA)': cannot convert argument 2 from 'WIN32_FIND_DATA *' to 'LPWIN32_FIND_DATAA'
错误会根据我的修复尝试而变化。我尝试了以下方法:
- 尝试将
FindFirstFile
更改为FindFirstFileW
/FindNextFileA
- 试图在目录字符串
L"C:\*"
前面放一个L
我看了以下相关问题:
- 使用 C 和 Windows 列出目录内容
- 如何使用Windows API列出目录中的文件?
但没有让它成功列出内容。我得到的最接近的是这段代码,它可以编译而没有错误:
#include <windows.h>
#include <iostream>
int main()
{
WIN32_FIND_DATA data;
HANDLE hFind = FindFirstFileW(L"C:\*", &data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
std::cout << data.cFileName << std::endl;
} while (FindNextFileW(hFind, &data));
FindClose(hFind);
}
}
这可以编译,但是当我运行二进制文件时,它会输出以下内容:
0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C 0000009A9DBAF32C
当我们在做这件事时,FindNextFile
、FindNextFileA
和FindNextFileW
有什么区别?我觉得这个问题与这些有某种关系?
FindNextFile
是一个宏,它解析为FindNextFileA
(ANSI)或FindNextFileW
(Unicode UTF16-LE),具体取决于是否定义了UNICODE
(和_UNICODE
)。
因此,您将WIN32_FIND_DATA
更改为WIN32_FIND_DATAA
,因为FindFirstFileA
需要参数的 ANSI 版本。
有关定义UNICODE
和_UNICODE
之间区别的说明,请参阅 https://devblogs.microsoft.com/oldnewthing/20040212-00/?p=40643
在你的第一个代码片段中,你显然是在用定义UNICODE
编译你的项目(从你能够无误地将WIN32_FIND_DATA
传递给FindNextFileW()
就可以看出来)。 定义UNICODE
后,WIN32_FIND_DATA
映射到WIN32_FIND_DATAW
。 但FindFirstFileA()
想要一个WIN32_FIND_DATAA
。 因此,该错误的最简单解决方案是将WIN32_FIND_DATA
更改为WIN32_FIND_DATAA
以满足对FindFirstFileA()
的调用。 但是接下来你会遇到一个新的错误,因为你会将一个WIN32_FIND_DATAA
传递给FindNextFileW()
,它想要一个WIN32_FIND_DATAW
。 因此,您需要调用FindNextFileA()
来修复该错误:
#include <iostream>
#include <string>
#include <Windows.h>
int wmain() {
WIN32_FIND_DATAA data;
std::string dir = "c:\* ";
HANDLE hFind = FindFirstFileA(dir.c_str(), &data); // DIRECTORY
if (hFind != INVALID_HANDLE_VALUE) {
do {
std::cout << data.cFileName << std::endl;
} while (FindNextFileA(hFind, &data));
FindClose(hFind);
}
return 0;
}
在第二个代码片段中,std::cout
没有用于wchar_t
数据的重载operator<<
,但它确实具有用于void*
的重载。WIN32_FIND_DATAW::cFileName
字段是一个wchar_t[]
数组,它衰减为指向第一个字符的wchar_t*
指针,并且所有指针都可以隐式转换为void*
。 所以这就是为什么你看到内存地址被打印出来。 您需要改用std::wcout
:
#include <iostream>
#include <string>
#include <windows.h>
int wmain()
{
WIN32_FIND_DATAW data;
std::wstring dir = L"c:\*";
HANDLE hFind = FindFirstFileW(dir.c_str(), &data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
std::wcout << data.cFileName << std::endl;
} while (FindNextFileW(hFind, &data));
FindClose(hFind);
}
}
大多数处理字符串数据的 Win32 API 都具有A
(ANSI) 和W
(宽、Unicode)风格,并提供基于TCHAR
的通用宏,以根据UNICODE
条件映射到其中一个宏。 在这种情况下,FindFirstFile()
映射到FindFirstFileA()
或FindFirstFileW()
,FindNextFile()
映射到FindNextFileA()
或FindNextFileW()
,WIN32_FIND_DATA
映射到WIN32_FIND_DATAA
或WIN32_FIND_DATAW
,等等。
因此,一般规则是,您在 API 函数调用中显式声明(或省略)的后缀也应根据需要在任何相关的变量声明中重复。 如果显式调用A
API 函数,请显式使用适当的A
变量类型。 如果显式调用W
API 函数,请显式使用适当的W
变量类型。 如果在 API 函数调用中省略A
/W
,请在变量声明中省略它(如果需要,请替换为TCHAR
的T
)。
- Active Directory:从网络服务帐户下运行的Windows服务调用ADsOpenObject时失败
- 如何从Windows控制台调用.exe(C++)以在不同的目录(或任何目录)中创建文件夹?
- 意外的 IConnectionPointImpl::不建议调用 Windows Embedded Compact 7
- 如何链接 DLL 以供 LoadLibrary() 使用(在 Windows 上的 C++ 中)并从调用 exe 导入变
- 程序在对mouse_event的 Windows API 调用中冻结
- Windows 是否可以调用静态库中的 WinMain 函数C++
- 从 dll 调用 opencv 垫到 Windows 表单,图像出现故障
- 从 Python 调用 Windows DLL 函数时出错
- 从 C# Windows 应用程序调用 C dll 会导致 svchost.exe 崩溃
- 何时调用 Windows 控制台应用程序需要 CoInitialize
- C 控制台程序中的内存泄漏调用Windows API
- Win32应用程序,在调用Windows内容之前调用自定义类方法
- 哪个线程调用windows proc回调函数
- 最好声明什么来调用Windows程序的约定
- 在资源管理器左窗格上两次调用Windows 7外壳扩展dll Initialize方法
- 从Windows窗体外部(从int WINAPI WinMain)调用Windows窗体方法
- 如何以编程方式调用Windows 7中的Ctrl+Alt+Del窗口
- 调用windows API内联程序集时出现问题
- 在MinGW上使用libffi调用Windows API
- 在ImpersonateLoggedOnUser()之后,为什么无法调用Windows API SetDisplayCo