C/C++获取Windows的文件占用大小
为了在 C++ 中递归计算文件夹的大小,使用 Windows API 中的 FindFirstFile
和 FindNextFile
函数。
#include <iostream>
#include <windows.h>
#include <string>
#include <locale>
/*
文件信息
*/
class file_instance{
public:
std::wstring* name;
std::wstring* path;
int type;
uintmax_t size;
file_instance* child;
file_instance* next;
file_instance* top;
std::wstring* get_path()
{
return this->path;
};
// 获取指定位置的下级文件信息
file_instance* getPointToFileInstance(int num)
{
file_instance* begin = this->child;
for(int i = 1;NULL!=begin;)
{
std::wstring nameContent = *(begin->name);
if(nameContent == L"." || nameContent==L"..")
{
begin = begin->next;
continue;
}
if(i==num&&NULL!=begin)
{
return begin;
}else if(NULL==begin){
std::wcout << L"查无对象" <<std::endl;
break;
}
begin = begin->next;
i++;
}
return NULL;
};
// 打印文件内容
void Print(){
std::wcout << L"当前所处的目录是:" << *(this->path) << L"\t"
<< L"文件夹名称:"<< *(this->name) << std::endl;
if(this->child==NULL)
{
std::wcout << L"current dir is empty!"<< std::endl;
}
else
{
file_instance* begin = this->child;
std::wcout << L"位置\t类型\t文件大小(MB)\t名称"<< std::endl;
int i = 1 ;
while(begin!=nullptr)
{
uintmax_t sizeNum = begin->size;
std::wstring nameContent = *(begin->name);
std::wstring typeContent;
if(nameContent == L"." || nameContent==L"..")
{
begin = begin->next;
continue;
}
if((begin->type)==1)
{
typeContent.append(L"DIR");
}else{
typeContent.append(L"FILE");
}
std::wcout<<i<<L"\t"<<typeContent<<L"\t"<< (sizeNum/1024/1024) <<L"\t" << nameContent <<std::endl;
begin = begin->next;
i++;
};
}
}
};
/*
递归遍历文件
*/
file_instance* get_folder_size(file_instance* parent) {
WIN32_FIND_DATAW find_data;
int fileLen = 0;
file_instance* start = NULL;
file_instance* next = NULL;
std::wstring* currentPath = new std::wstring(parent->path->c_str());
HANDLE find_handle = FindFirstFileW((*(parent->path) + L"\\*").c_str(), &find_data);
if (find_handle != INVALID_HANDLE_VALUE) {
do {
file_instance* childDirector = new file_instance();
childDirector->name = new std::wstring(find_data.cFileName);
std::wstring* childDirectorPath = &(new std::wstring(*currentPath))->append(L"\\").append(find_data.cFileName);
childDirector->path = childDirectorPath;
childDirector->top = parent;
// 文件夹
if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (wcscmp(find_data.cFileName, L".") != 0 && wcscmp(find_data.cFileName, L"..") != 0) {
childDirector->type = 1;
get_folder_size(childDirector);
}
}
// 普通文件
else
{
childDirector->type = 2;
childDirector->size += find_data.nFileSizeLow;
childDirector->size += find_data.nFileSizeHigh * (static_cast<uintmax_t>(MAXDWORD) + 1);
}
parent->size += childDirector->size;
//
if(next==nullptr)
{
start = childDirector;
next = childDirector;
}else{
next->next = childDirector;
next = next->next;
}
} while (FindNextFileW(find_handle, &find_data));
FindClose(find_handle);
}
parent->child = start;
return parent;
}
// 字符串数字转换为数值
int getNumber(std::string numberString)
{
setlocale( LC_ALL, "chs" );
int number = -1;
try {
number = std::stoi(numberString);
} catch (std::invalid_argument& e) {
} catch (std::out_of_range& e) {
}
return number;
}
int main() {
// ***************************初始化********************************
// 解决wstring打印不显示的问题
std::wcout.imbue(std::locale("chs"));
// 解决中文乱码问题
system("chcp 65001");
// ***************************扫描文件信息****************************
// 创建文件根节点
file_instance* root = new file_instance();
std::wstring* name = new std::wstring();
root->name = name;
root->path = new std::wstring(L"");
root->type = 1;
std::wcout << L"请输入扫描路径:"<< std::endl;
std::getline(std::wcin,*(root->path));
std::wcout <<L"正在扫描" << root->path->c_str()<< L"..." << std::endl;
// 递归扫描获取文件信息
root = get_folder_size(root);
std::wcout <<L"扫描完成!" << std::endl;
std::wcout <<L"当前所在目录是:"<< root->path->c_str()<<root->name->c_str()<<std::endl;
// ***************************文件信息查看说明********************************
// q:退出
// w:返回上一级
// p:查看当前位置下的文件
// 数值:查看对应位置文件夹下的文件信息
// 浏览文件信息
file_instance* begin = root;
std::string line;
while(line!=std::string("q"))
{
std::cout << "option>>" <<std::endl;
std::getline(std::cin,line);
if(line==std::string("w"))
{
if(NULL!=begin->top){
begin = begin->top;
begin->Print();
}
else
{
std::wcout << "not exist" << std::endl;
}
}
else if(line==std::string("p"))
{
if(NULL!=begin){
begin->Print();
}
else
{
std::wcout << "not exist" << std::endl;
}
}
else
{
int number = getNumber(line);
if(number!=-1)
{
if(NULL!=begin)
{
file_instance* target = begin->getPointToFileInstance(number);
if(NULL!=target)
{
begin = target;
target->Print();
}else
{
std::wcout << "not exist" << std::endl;
}
}else
{
begin = root->child;
}
}
}
}
// ***************************结束********************************
return 0;
}