Created
March 12, 2017 07:51
-
-
Save leozzyzheng/7174db44c60f43cdfe7ba0c72b357297 to your computer and use it in GitHub Desktop.
List directory in win32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <iostream> | |
#include <stack> | |
#include <string> | |
#include <windows.h> | |
class DirInfo { | |
public: | |
DirInfo(const wchar_t* dir_path) { | |
path = CleanPath(dir_path); | |
return_dot_and_dotdot = true; | |
list_into_dir_flag = true; | |
} | |
~DirInfo() { | |
ResetList(); | |
} | |
static std::wstring CleanPath(const std::wstring& path) { | |
if (path.empty()) { | |
return L""; | |
} | |
std::wstring copy = path; | |
size_t offset = 0; | |
while ((offset = copy.find_first_of(L'\\', offset)) != std::wstring::npos) { | |
copy.replace(offset, 1, L"/"); | |
} | |
if (copy.find_last_of(L'/') == copy.size() - 1) { | |
copy.resize(copy.size() - 1); | |
} | |
return std::move(copy); | |
} | |
bool IsValid() const { | |
auto attr = ::GetFileAttributesW(path.c_str()); | |
if (attr != INVALID_FILE_ATTRIBUTES) { | |
if (attr && FILE_ATTRIBUTE_DIRECTORY) { | |
return true; | |
} | |
} | |
return false; | |
} | |
void SetListRetrunDotAndDotDot(bool will_return) { | |
return_dot_and_dotdot = will_return; | |
} | |
bool ListFiles(WIN32_FIND_DATAW* file_data, std::wstring* full_path) { | |
if (file_data == NULL) { | |
assert(file_data != NULL); | |
return false; | |
} | |
HANDLE file_handle; | |
if (list_into_dir_flag) { | |
list_into_dir_flag = false; | |
std::wstring dir; | |
if (dir_stack.empty()) { | |
dir = path; | |
} else { | |
dir = dir_stack.top(); | |
} | |
file_handle = ::FindFirstFileW((dir + L"/*").c_str(), file_data); | |
if (file_handle == INVALID_HANDLE_VALUE) { | |
return false; | |
} | |
if (dir_stack.empty()) { | |
handle_stack.push(file_handle); | |
dir_stack.push(path); | |
} else { | |
assert(handle_stack.top() == INVALID_HANDLE_VALUE); | |
handle_stack.pop(); | |
handle_stack.push(file_handle); | |
} | |
} else { | |
if (handle_stack.empty()) { | |
return false; | |
} | |
file_handle = handle_stack.top(); | |
while (::FindNextFileW(file_handle, file_data) == FALSE) { | |
::FindClose(file_handle); | |
handle_stack.pop(); | |
dir_stack.pop(); | |
if (handle_stack.empty()) { | |
return false; | |
} | |
file_handle = handle_stack.top(); | |
} | |
} | |
auto is_dot_or_dotdot = wcscmp(file_data->cFileName, L".") == 0 || | |
wcscmp(file_data->cFileName, L"..") == 0; | |
if (is_dot_or_dotdot && !return_dot_and_dotdot) { | |
return ListFiles(file_data, full_path); | |
} | |
std::wstring file_full_path = dir_stack.top() + L"/" + file_data->cFileName; | |
if (!is_dot_or_dotdot && file_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { | |
handle_stack.push(INVALID_HANDLE_VALUE); | |
dir_stack.push(file_full_path); | |
list_into_dir_flag = true; | |
} | |
if (full_path != NULL) { | |
*full_path = std::move(file_full_path); | |
} | |
return true; | |
} | |
void ResetList() { | |
list_into_dir_flag = true; | |
while (!handle_stack.empty()) { | |
auto handle = handle_stack.top(); | |
if (handle != INVALID_HANDLE_VALUE) { | |
::FindClose(handle); | |
} | |
handle_stack.pop(); | |
} | |
while (!dir_stack.empty()) { | |
dir_stack.pop(); | |
} | |
} | |
private: | |
std::wstring path; | |
bool return_dot_and_dotdot; | |
bool list_into_dir_flag; | |
std::stack<HANDLE> handle_stack; | |
std::stack<std::wstring> dir_stack; | |
}; | |
int main() { | |
std::wstring cmd; | |
LPWSTR *szArgList; | |
int argCount; | |
szArgList = CommandLineToArgvW(GetCommandLine(), &argCount); | |
if (szArgList != NULL && argCount > 1) { | |
cmd = szArgList[1]; | |
} | |
DirInfo dir(cmd.c_str()); | |
dir.SetListRetrunDotAndDotDot(false); | |
WIN32_FIND_DATAW file_data = { 0 }; | |
std::wstring full_path; | |
int file_count = 0; | |
int dir_count = 0; | |
while (dir.ListFiles(&file_data, &full_path)) { | |
std::wcout << full_path; | |
if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { | |
std::cout << " is directory" << std::endl; | |
++dir_count; | |
} else { | |
std::cout << " is file" << std::endl; | |
++file_count; | |
} | |
} | |
std::cout << "total:" << dir_count << "directories," << file_count << "files" << std::endl; | |
system("pause"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment