// 返回位元組數,選擇性輸出檔案/資料夾計數
ULONGLONG GetFolderSize(LPCTSTR szPath, DWORD* pdwFiles = NULL, DWORD* pdwFolders = NULL);
ULONGLONG GetFolderSize(LPCTSTR szPath, DWORD* pdwFiles, DWORD* pdwFolders)
{
TCHAR szFindPath[MAX_PATH];
TCHAR szFilter[MAX_PATH];
WIN32_FIND_DATA fd;
HANDLE hFind = INVALID_HANDLE_VALUE;
ULONGLONG ullSize = 0;
// 構建搜尋路徑:path\*
_tcscpy_s(szFindPath, szPath);
PathAddBackslash(szFindPath); // 確保結尾有 \
_tcscpy_s(szFilter, szFindPath);
_tcscat_s(szFilter, _T("*.*"));
hFind = FindFirstFile(szFilter, &fd);
if (hFind == INVALID_HANDLE_VALUE) return 0;
do {
// 跳過 . 和 ..
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (!_tcscmp(fd.cFileName, _T(".")) || !_tcscmp(fd.cFileName, _T("..")))
continue;
// 遞歸子目錄
TCHAR szSubPath[MAX_PATH];
_tcscpy_s(szSubPath, szFindPath);
_tcscat_s(szSubPath, fd.cFileName);
ullSize += GetFolderSize(szSubPath, pdwFiles, pdwFolders);
if (pdwFolders) (*pdwFolders)++;
}
else {
// 檔案大小 (僅低 32 位,大於 4GB 需組合 nFileSizeHigh)
ullSize += fd.nFileSizeLow;
if (pdwFiles) (*pdwFiles)++;
}
} while (FindNextFile(hFind, &fd));
FindClose(hFind);
return ullSize;
}
| API | 用途 |
|---|---|
FindFirstFile / FindNextFile | 枚舉目錄項目 |
WIN32_FIND_DATA | 項目資訊:屬性、檔名、大小、時間 |
FILE_ATTRIBUTE_DIRECTORY | 判斷目錄屬性 |
PathAddBackslash | Shlwapi.h,安全補齊路徑分隔符 |
ULONGLONG | 64 位無號整數,支援 >4GB 資料夾 |
ULARGE_INTEGER li;
li.LowPart = fd.nFileSizeLow;
li.HighPart = fd.nFileSizeHigh;
ullSize += li.QuadPart;
#include <filesystem>
#include <system_error>
uintmax_t GetFolderSizeModern(const std::wstring& path, std::error_code& ec)
{
uintmax_t total = 0;
for (auto& entry : std::filesystem::recursive_directory_iterator(path, ec)) {
if (ec) break;
if (entry.is_regular_file(ec)) total += entry.file_size(ec);
}
return total;
}
優點:跨平台、自動處理迴圈連結、例外安全、程式碼極簡。