是否有任何API在C ++获取指定文件夹的大小?
如果没有,我怎样才能得到包括所有子文件夹和文件的文件夹的总大小?
其实我不想使用任何第三方库。 只是想在纯C ++中实现。
如果您使用MSVC ++,则将<filesystem>
“作为标准C ++”。 但使用boost或MSVC – 都是“纯C ++”。
如果你不想使用boost,只有C ++ std :: library这个答案有点接近。 正如你在这里看到的,有一个文件系统库的建议(修订4) 。 在这里你可以阅读:
图书馆的Boost版本已经被广泛使用了十年。 该库的Dinkumware版本基于N1975(等同于Boost库的版本2),附带Microsoft Visual C ++ 2012。
为了说明这个用法,我修改了@Nayana Adassuriya的答案,做了很小的修改(好吧,他忘了初始化一个变量,而我使用了unsigned long long
,最重要的是使用: path filePath(complete (dirIte->path(), folderPath));
在调用其他函数之前恢复完整的路径)。 我已经测试,并在Windows 7中运行良好。
#include <iostream> #include <string> #include <filesystem> using namespace std; using namespace std::tr2::sys; void getFoldersize(string rootFolder,unsigned long long & f_size) { path folderPath(rootFolder); if (exists(folderPath)) { directory_iterator end_itr; for (directory_iterator dirIte(rootFolder); dirIte != end_itr; ++dirIte ) { path filePath(complete (dirIte->path(), folderPath)); try{ if (!is_directory(dirIte->status()) ) { f_size = f_size + file_size(filePath); }else { getFoldersize(filePath,f_size); } }catch(exception& e){ cout << e.what() << endl; } } } } int main() { unsigned long long f_size=0; getFoldersize("C:\\Silvio",f_size); cout << f_size << endl; system("pause"); return 0; }
让操作系统为你做:
long long int getFolderSize(string path) { // command to be executed std::string cmd("du -sb "); cmd.append(path); cmd.append(" | cut -f1 2>&1"); // execute above command and get the output FILE *stream = popen(cmd.c_str(), "r"); if (stream) { const int max_size = 256; char readbuf[max_size]; if (fgets(readbuf, max_size, stream) != NULL) { return atoll(readbuf); } pclose(stream); } // return error val return -1; }
文件夹中的文件大小请查看此链接
#include <iostream> #include <windows.h> #include <string> using namespace std; __int64 TransverseDirectory(string path) { WIN32_FIND_DATA data; __int64 size = 0; string fname = path + "\\*.*"; HANDLE h = FindFirstFile(fname.c_str(),&data); if(h != INVALID_HANDLE_VALUE) { do { if( (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { // make sure we skip "." and "..". Have to use strcmp here because // some file names can start with a dot, so just testing for the // first dot is not suffient. if( strcmp(data.cFileName,".") != 0 &&strcmp(data.cFileName,"..") != 0) { // We found a sub-directory, so get the files in it too fname = path + "\\" + data.cFileName; // recurrsion here! size += TransverseDirectory(fname); } } else { LARGE_INTEGER sz; // All we want here is the file size. Since file sizes can be larger // than 2 gig, the size is reported as two DWORD objects. Below we // combine them to make one 64-bit integer. sz.LowPart = data.nFileSizeLow; sz.HighPart = data.nFileSizeHigh; size += sz.QuadPart; } }while( FindNextFile(h,&data) != 0); FindClose(h); } return size; } int main(int argc, char* argv[]) { __int64 size = 0; string path; size = TransverseDirectory("c:\\dvlp"); cout << "\n\nDirectory Size = " << size << "\n"; cin.ignore(); return 0; }
有关更多详细信息,请点击此处
你可以用这种方式使用boost。 你可以尝试更深入地优化它。
#include <iostream> #include <string> #include <boost/filesystem.hpp> #include <boost/filesystem/operations.hpp> #include <boost/algorithm/string.hpp> using namespace std; namespace bsfs = boost::filesystem; void getFoldersize(string rootFolder,long & file_size){ boost::replace_all(rootFolder, "\\\\", "\\"); bsfs::path folderPath(rootFolder); if (bsfs::exists(folderPath)){ bsfs::directory_iterator end_itr; for (bsfs::directory_iterator dirIte(rootFolder); dirIte != end_itr; ++dirIte ) { bsfs::path filePath(dirIte->path()); try{ if (!bsfs::is_directory(dirIte->status()) ) { file_size = file_size + bsfs::file_size(filePath); }else{ getFoldersize(filePath.string(),file_size); } }catch(exception& e){ cout << e.what() << endl; } } } } int main(){ long file_size =0; getFoldersize("C:\\logs",file_size); cout << file_size << endl; system("pause"); return 0; }
文件系统函数是每个操作系统不可或缺的组成部分,主要用C语言和汇编语言编写,而不是C ++,每个C ++库实现都是以这种或那种方式包装这个函数的。 考虑到这些努力,如果你不会在不同的操作系统中使用你的实现,那么直接使用这个函数是一个好主意,并且可以节省一些开销和时间。
最好的祝福。
我有我的类型定义文件:
typedef std::wstring String; typedef std::vector<String> StringVector; typedef unsigned long long uint64_t;
代码是:
uint64_t CalculateDirSize(const String &path, StringVector *errVect = NULL, uint64_t size = 0) { WIN32_FIND_DATA data; HANDLE sh = NULL; sh = FindFirstFile((path + L"\\*").c_str(), &data); if (sh == INVALID_HANDLE_VALUE ) { //if we want, store all happened error if (errVect != NULL) errVect ->push_back(path); return size; } do { // skip current and parent if (!IsBrowsePath(data.cFileName)) { // if found object is ... if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) // directory, then search it recursievly size = CalculateDirSize(path + L"\\" + data.cFileName, NULL, size); else // otherwise get object size and add it to directory size size += (uint64_t) (data.nFileSizeHigh * (MAXDWORD ) + data.nFileSizeLow); } } while (FindNextFile(sh, &data)); // do FindClose(sh); return size; } bool IsBrowsePath(const String& path) { return (path == _T(".") || path == _T("..")); }
这使用UNICODE并返回失败的dirs,如果你想要的话。
致电使用:
StringVector vect; CalculateDirSize(L"C:\\boost_1_52_0", &vect); CalculateDirSize(L"C:\\boost_1_52_0");
但是,不要传递size
//use FAT32 #undef UNICODE // to flag window deactive unicode #include<Windows.h> //to use windows api #include<iostream> #include<iomanip> #include<cstring> #include<string> #include<algorithm> using namespace std; #pragma pack(1) //tell compiler do'nt do prag struct BPB { BYTE JMP[3]; BYTE OEM[8]; WORD NumberOfBytesPerSector; BYTE NumberOfSectorsPerCluster; WORD NumberOfReservedSectors; BYTE NumberOfFATs; WORD NumberOfRootEntries16; WORD LowNumbferOfSectors; BYTE MediaDescriptor; WORD NumberOfSectorsPerFAT16; WORD NumberOfSectorsPerTrack; WORD NumberOfHeads; DWORD NumberOfHiddenSectors; DWORD HighNumberOfSectors; DWORD NumberOfSectorsPerFAT32; WORD Flags; WORD FATVersionNumber; DWORD RootDirectoryClusterNumber; WORD FSInfoSector; WORD BackupSector; BYTE Reserver[12]; BYTE BiosDrive; BYTE WindowsNTFlag; BYTE Signature; DWORD VolumeSerial; BYTE VolumeLabel[11]; BYTE SystemID[8]; BYTE CODE[420]; WORD BPBSignature; }; //----------------------------------------------------------- struct DirectoryEntry { BYTE Name[11]; BYTE Attributes; BYTE Reserved; BYTE CreationTimeTenth; WORD CreationTime; WORD CreationDate; WORD LastAccessTime; WORD HiClusterNumber; WORD WriteTime; WORD WriteDate; WORD LowClusterNumber; DWORD FileSize; //acual size of file }; //--------------------------------------------------- void dirFunction(string s){ string path = "\\\\.\\" + s + ":"; HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open partition BPB bootSector;//var from bootSector structure DWORD readBytes = 0; if (hFile == INVALID_HANDLE_VALUE) { cout << "Error " << GetLastError()<<endl; return; } ReadFile(hFile, (BYTE*)&bootSector, sizeof(bootSector), &readBytes, 0);//read partition and load bootSector information inside our structure LONG t = 0; ULONG distance = bootSector.NumberOfReservedSectors + bootSector.NumberOfFATs*bootSector.NumberOfSectorsPerFAT32;//distance from begine until Root Directory or content of partetion distance *= bootSector.NumberOfBytesPerSector;//convert distance number to bytes value SetFilePointer(hFile, distance, &t, FILE_BEGIN);//set pointer to root directory begine or begine of data int clusterSize = bootSector.NumberOfBytesPerSector*bootSector.NumberOfSectorsPerCluster; //cluster size int NumberOfEntries = clusterSize / sizeof(DirectoryEntry); //number of record inside cluster DirectoryEntry* root = new DirectoryEntry[NumberOfEntries];//descripe the partetion ReadFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0); DWORD clusterNumber; for (int i = 0; i < NumberOfEntries; i++) { if (root[i].Name[0] == 0)//there no entery after this break; if (root[i].Name[0] == 0xE5) continue; if ((root[i].Attributes & 0xF) == 0xF) continue; for (int j = 0; j < 8; j++) cout << root[i].Name[j]; if((root[i].Attributes & 0x10) != 0x10){ cout<<"."; for (int j = 8; j < 11; j++) cout << root[i].Name[j]; } if ((root[i].Attributes & 0x10) == 0x10){ cout << "\t<Folder>" ; }else{ cout<<"\t<File>" ; } clusterNumber = root[i].HiClusterNumber << 16; clusterNumber |= root[i].LowClusterNumber; cout <<"\t"<<root[i].FileSize<<"bytes" << "\t" << clusterNumber<<"cluster" << endl; } CloseHandle(hFile); } //--------------------------------------------------------------- string convertLowerToUpper(string f){ string temp = ""; for (int i = 0; i < f.size(); i++){ temp += toupper(f[i]); } return temp; } //--------------------------------------------------------------- string getFileName(BYTE filename[11]){ string name = ""; for (int i = 0; i < 8; i++){ if (filename[i] != ' ') name += filename[i]; } return (name); } //------------------------------------------------------------------ int findEntryNumber(DirectoryEntry* root, int NumberOfEntries, string required){ string n; int j = 0; for (int i = 0; i < NumberOfEntries; i++){ if (strcmp((getFileName(root[i].Name).c_str()), convertLowerToUpper(required).c_str()) == 0){ return i; } } return -1; } //--------------------------------------------------------------- void typeFunction(string fileName, string s){ string path = "\\\\.\\" + s + ":"; HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open partition BPB bootSector;//var from bootSector structure DWORD readBytes = 0; if (hFile == INVALID_HANDLE_VALUE) { cout << "Error " << GetLastError()<<endl; return; } ReadFile(hFile, (BYTE*)&bootSector, sizeof(bootSector), &readBytes, 0);//read partition and load bootSector information inside our structure LONG t = 0; ULONG distance = bootSector.NumberOfReservedSectors + bootSector.NumberOfFATs*bootSector.NumberOfSectorsPerFAT32;//distance from begine until Root Directory or content of partetion distance *= bootSector.NumberOfBytesPerSector;//convert distance number to bytes value SetFilePointer(hFile, distance, &t, FILE_BEGIN);//set pointer to root directory begine or begine of data int clusterSize = bootSector.NumberOfBytesPerSector*bootSector.NumberOfSectorsPerCluster; //cluster size int NumberOfEntries = clusterSize / sizeof(DirectoryEntry); //number of record inside cluster DirectoryEntry* root = new DirectoryEntry[NumberOfEntries];//descripe the partetion ReadFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0); DWORD clusterNumber; int index = findEntryNumber(root, NumberOfEntries, fileName); if (index == -1){ cout << "File is not found" << endl; return; } if (((root[index].Attributes & 0x10) == 0x10) ){ cout << "Is not file name" << endl; return; } clusterNumber = root[index].HiClusterNumber << 16; clusterNumber |= root[index].LowClusterNumber; ULONG temp = (clusterNumber - 2) * clusterSize; distance += temp; t = 0; SetFilePointer(hFile, distance, &t, FILE_BEGIN); BYTE* buffer = new BYTE[clusterSize]; readBytes = 0; ReadFile(hFile, (BYTE*)buffer, clusterSize, &readBytes, 0); for (int i = 0; i < root[index].FileSize; i++){ cout << buffer[i]; } cout << endl; CloseHandle(hFile); } //---------------------------------------------------------------------- void delFunction(string filename, string s){ string path = "\\\\.\\" + s + ":"; HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open partition BPB bootSector;//var from bootSector structure DWORD readBytes = 0; if (hFile == INVALID_HANDLE_VALUE) { cout << "Error " << GetLastError()<<endl; return; } ReadFile(hFile, (BYTE*)&bootSector, sizeof(bootSector), &readBytes, 0);//read partition and load bootSector information inside our structure LONG t = 0; ULONG distance = bootSector.NumberOfReservedSectors + bootSector.NumberOfFATs*bootSector.NumberOfSectorsPerFAT32;//distance from begine until Root Directory or content of partetion distance *= bootSector.NumberOfBytesPerSector;//convert distance number to bytes value SetFilePointer(hFile, distance, &t, FILE_BEGIN);//set pointer to root directory begine or begine of data int clusterSize = bootSector.NumberOfBytesPerSector*bootSector.NumberOfSectorsPerCluster; //cluster size int NumberOfEntries = clusterSize / sizeof(DirectoryEntry); //number of record inside cluster DirectoryEntry* root = new DirectoryEntry[NumberOfEntries];//descripe the partetion ReadFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0); DWORD clusterNumber; readBytes = 0; t = 0; int index = findEntryNumber(root, NumberOfEntries, filename); if (index == -1){ cout << "FIle is not found" << endl; return; } if ((root[index].Attributes & 0x10) == 0x10){ cout << "Is not file name" << endl; return; } //delete file root[index].Name[0] = 0xE5; SetFilePointer(hFile, distance, &t, FILE_BEGIN); WriteFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0); cout<<filename<<" is deleted\n"; CloseHandle(hFile); } //---------------------------------------------------------------------- string removeExtention(string s){ string t = ""; for (int i = 0; i < s.size(); i++){ if (s[i] == '.')break; t += s[i]; } return t; } //------------------------------------------------------------------- void main() { string swich_value; string directory; string file_name; //dirFunction("G"); cout<<"plz, Enter single Partition character ------> example E or G\n\n"; cin>>directory; string path = "\\\\.\\" + directory + ":"; cout<<"current directory is "<<path<<endl; cout<<"Enter Options: \n1- dir \n2- type file_name.extention \n3- del file_name.extention\n\n"; again: cin>>swich_value; if(swich_value.at(1)!='i') cin>>file_name; string answer; switch(swich_value.at(1)){ case 'i': dirFunction(directory); cout<<"\nare you want to do another process: y or n?"; cin>>answer; if (answer.at(0)=='y') goto again; break; case 'y': typeFunction(removeExtention(file_name), directory); cout<<"\nare you want to do another process: y or n?"; cin>>answer; if (answer.at(0)=='y') goto again; break; case 'e': delFunction(removeExtention(file_name), directory); cout<<"\nare you want to do another process: y or n?"; cin>>answer; if (answer.at(0)=='y') goto again; break; } }
你可以使用“boost :: filesystem”
#include <boost/filesystem.hpp> namespace fs = boost::filesystem; unsigned long long int get_directory_size(const fs::path& directory){ if (!fs::exists(directory)) return 0; if (fs::is_directory(directory)){ unsigned long long int ret_size = 0; fs::directory_iterator m_dir_itr(directory); for (m_dir_itr = fs::begin(m_dir_itr); m_dir_itr != fs::end(m_dir_itr); ++m_dir_itr){ fs::directory_entry m_dir_entry = *m_dir_itr; if (fs::is_regular_file(m_dir_entry.path())){ ret_size += fs::file_size(m_dir_entry.path()); }else if (fs::is_directory(m_dir_entry.path())){ ret_size += get_directory_size(m_dir_entry.path()); } } return ret_size; } else if (fs::is_regular_file(directory)){ return fs::file_size(directory); } return 0; } #include <stdio.h> int main(int /*argc*/, char** /*argv*/) { // Assuming 'C:/Folder' be any directory then its size can be found using auto folder_size = get_directory_size("C:/Folder"); printf("Size of 'C:/Folder' is %d\n",folder_size); return 0; }
尝试使用GetFileSizeEx函数。 以下是一些示例代码。 您需要从LARGE_INTEGER联合中获取大小。
#include <iostream> #include <windows.h> #include <stdio.h> #include <io.h> using namespace std; int main() { FILE *fp; fp = fopen("C:\test.txt","r"); int fileNo = _fileno(fp); HANDLE cLibHandle = (HANDLE)_get_osfhandle(fileNo); long int fileSize = 0; LARGE_INTEGER fileSizeL; GetFileSizeEx(cLibHandle, &fileSizeL); return 0; }