指定されたフォルダのサイズを取得するためのc++のAPIはありますか?
そうでない場合、すべてのサブフォルダーとファイルを含むフォルダーの合計サイズを取得するにはどうすればよいですか?
指定されたフォルダのサイズを取得するためのc++のAPIはありますか?
そうでない場合、すべてのサブフォルダーとファイルを含むフォルダーの合計サイズを取得するにはどうすればよいですか?
OSに任せてみませんか:
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;
}
実際、サードパーティのライブラリは使用したくありません。純粋な C++ で実装したいだけです。
MSVC++ を使用している場合は、<filesystem>
「標準 C++ として」使用できます。
ただし、ブーストまたは MSVC を使用すると、どちらも「純粋な C++」になります。
ブーストを使用せず、C++ std:: ライブラリのみを使用する場合、この回答はやや近いです。ここでわかるように、 Filesystem Library Proposal (Revision 4) があります。ここで読むことができます:
ライブラリの Boost バージョンは、10 年間広く使用されています。N1975 (Boost ライブラリのバージョン 2 に相当) に基づく Dinkumware バージョンのライブラリには、Microsoft Visual C++ 2012 が同梱されています。
使用法を説明するために、@Nayana Adassuriya の回答をごくわずかな変更を加えて適応させました (OK、彼は 1 つの変数を初期化するのを忘れていました。私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;
}
この方法でブーストを使用できます。より深く最適化を試みることができます。
#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;
}
フォルダ内のファイルのサイズ このリンクをご覧ください
#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;
}
詳細については、ここをクリックしてください
ファイルシステム関数は、各オペレーティングシステムの不可欠な部分であり、主にC ++ではなくCとアセンブラで記述されています。このための各C++ライブラリの実装は、何らかの形でこの関数のラッパーです。労力を考慮し、異なるOSで実装を使用しない場合は、この関数を直接使用して、オーバーヘッドと時間を節約することをお勧めします。
よろしくお願いします。
タイプ定義ファイルには次のものがあります。
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 を使用し、必要に応じて失敗したディレクトリを返します。
呼び出すには:
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;
}
}
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;
}