Как найти размер всех файлов, находящихся внутри папки?

Есть ли какой-либо API в для получения размера указанной папки?

Если нет, как я могу получить общий размер папки, включая все подпапки и файлы?

Ответ 1

На самом деле я не хочу использовать стороннюю библиотеку. Просто хочу к реализовать в чистом С++.

Если вы используете MSVС++, вы <filesystem> "в качестве стандартного С++" . Но с использованием boost или MSVC - оба являются "чистыми С++".

Если вы не хотите использовать boost, и только С++ std:: library, этот ответ несколько близок. Как вы можете видеть здесь, есть предложение библиотеки файловой системы (версия 4). Здесь вы можете прочитать:

Расширяемая версия библиотеки широко используется в течение десяти года. Версия библиотеки Dinkumware, основанная на N1975 (эквивалентно версии 2 библиотеки Boost), поставляется с Microsoft Visual С++ 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;
}

Ответ 2

Как насчет того, чтобы ОС могла сделать это для вас:

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;
}

Ответ 3

Вы можете использовать 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;
    }

Ответ 4

Размер файлов в папке Посмотрите на эту ссылку.

#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;
}

Подробнее PLease CLick Здесь

Ответ 5

Функции файловой системы являются неотъемлемой частью каждой оперативной системы, написанной в основном на C и ассемблере, а не на С++, каждая реализация библиотеки С++ для этого в той или иной мере является оболочкой этих функций. Принимая во внимание усилия, и если вы не будете использовать свою реализацию в разных ОС, возможно, это хорошая идея использовать эти функции напрямую и сохранить некоторые накладные расходы и время.

С уважением.

Ответ 6

У меня есть файл определения типов с помощью:

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

Ответ 7

//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;


}
}

Ответ 8

Вы можете использовать "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;
}

Ответ 9

С введением std::filesystem вам больше не нужно использовать какие-либо системные API или любые внешние библиотеки.

#include <filesystem>
namespace n_fs = ::std::filesystem;
double archive::getFolderSize(std::string path)
{
        double r = 0.0;
        try{
           if (!n_fs::is_directory(path))
           {
                r += (double)n_fs::file_size(path);
           }
           else
           {
                for(auto entry: n_fs::directory_iterator(path))
                getFolderSize(entry.path().string());
            }
        } 
        catch(exception& e)
        { 
            std::cout << e.what() << std::endl();
        }
        return r;
}

int main(){
    double folderSize = getFolderSize("~/dev/"); //Replace with your path
    std::cout << "Size of Folder: " << folderSize;
}

Ответ 10

Попробуйте использовать функцию 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;
}

Ответ 11

5 лет, а не простое решение со стандартом C++, поэтому я хотел бы предложить свое решение этого вопроса:

uint64_t GetDirSize(const std::string &path)
{
    uint64_t size = 0;
    for (const auto & entry : std::experimental::filesystem::directory_iterator(path))
    {
        if(entry.status().type() == std::experimental::filesystem::file_type::regular)
            size += std::experimental::filesystem::file_size(entry.path());
        if (entry.status().type() == std::experimental::filesystem::file_type::directory)
            size += GetDirSize(entry.path().generic_string());
    }
    return size;
}

Используйте его, например, вызывая GetDirSize("C:\\dir_name") если вы используете Windows.