Який найкращий спосіб обчислити розмір каталогу в .NET?


78

Я написав наступну процедуру для ручного переходу по каталогу та обчислення її розміру в C # /. NET:


protected static float CalculateFolderSize(string folder)
{
    float folderSize = 0.0f;
    try
    {
        //Checks if the path is valid or not
        if (!Directory.Exists(folder))
            return folderSize;
        else
        {
            try
            {
                foreach (string file in Directory.GetFiles(folder))
                {
                    if (File.Exists(file))
                    {
                        FileInfo finfo = new FileInfo(file);
                        folderSize += finfo.Length;
                    }
                }

                foreach (string dir in Directory.GetDirectories(folder))
                    folderSize += CalculateFolderSize(dir);
            }
            catch (NotSupportedException e)
            {
                Console.WriteLine("Unable to calculate folder size: {0}", e.Message);
            }
        }
    }
    catch (UnauthorizedAccessException e)
    {
        Console.WriteLine("Unable to calculate folder size: {0}", e.Message);
    }
    return folderSize;
}

У мене є програма, яка запускає цю процедуру неодноразово для великої кількості папок. Цікаво, чи існує більш ефективний спосіб обчислення розміру папки за допомогою .NET? Я не побачив нічого конкретного в рамках. Чи повинен я використовувати P / Invoke та Win32 API? Який найефективніший спосіб обчислення розміру папки в .NET?

Відповіді:


25

Я не вірю, що існує Win32 API для обчислення місця, зайнятого каталогом, хоча я маю на це коригувати. Якби це було тоді, я б припустив, що Explorer використовував би його. Якщо ви отримаєте Властивості великого каталогу в Провіднику, час, необхідний для надання вам розміру папки, пропорційний кількості файлів / підкаталогів, які вона містить.

Ваша рутина здається досить акуратною та простою. Майте на увазі, що ви обчислюєте суму довжин файлів, а не фактичне місце, зайняте на диску. Простір, витрачений марно витраченим простором в кінці кластерів, потоків файлів тощо, ігнорується.


6
Цей метод також ігнорує з'єднання, жорсткі посилання, стиснення та зберігання в автономному режимі.
Антон Тихий,

EnumerateFiles також може бути кращим, оскільки в них можуть бути папки з файлами більше 100 000. З'єднання, як згадувалося вище, можуть спричинити нескінченну рекурсію IIRC.
Просто ще один метапрограміст

1
Існує API. FileSystemObject (COM). Використовуйте GetFolder () - метод msdn.microsoft.com/en-us/library/f1xtf7ta(v=vs.84).aspx та властивість Size-msdn.microsoft.com/en-us/library/2d66skaf(v=vs .84) .aspx
Даніель Фішер lennybacon

@DanielFisherlennybacon чи знаєте ви, як це реалізовано? Чи має fso.GetFolder().Sizeцикл рекурсивно DirSize()робить або , можливо , Windows , відстежує розмір папки? Який "розмір" він повертає ?
jfs

Чому б не використовувати цю функцію 'GetDiskFreeSpaceEx'? Посилання: msdn.microsoft.com/en-us/library/windows/desktop/…
Орі

69

Ні, це виглядає як рекомендований спосіб обчислення розміру каталогу, відповідний метод, включений нижче:

public static long DirSize(DirectoryInfo d) 
{    
    long size = 0;    
    // Add file sizes.
    FileInfo[] fis = d.GetFiles();
    foreach (FileInfo fi in fis) 
    {      
        size += fi.Length;    
    }
    // Add subdirectory sizes.
    DirectoryInfo[] dis = d.GetDirectories();
    foreach (DirectoryInfo di in dis) 
    {
        size += DirSize(di);   
    }
    return size;  
}

Ви можете зателефонувати з коренем як:

Console.WriteLine("The size is {0} bytes.", DirSize(new DirectoryInfo(targetFolder));

... де targetFolderрозмір папки для обчислення.


шукати "Наступний приклад коду демонструє, як розрахувати розмір каталогу;" і це те саме, що у наведеному вище прикладі.
mbrownnyc


1
@ladenedge оновлене посилання? Цей приведе вас до v2.0 ... Посилання на відповідь правильне.
kzfabi

До речі: посилання на рекомендований спосіб більше не містить приклад. Здається, MSDN оновлено, і він загубився.
kzfabi

4
Використовуйте EnumerateFiles та EnumerateDirectories
Mauro Sampietro

34
DirectoryInfo dirInfo = new DirectoryInfo(@strDirPath);
long dirSize = await Task.Run(() => dirInfo.EnumerateFiles( "*", SearchOption.AllDirectories).Sum(file => file.Length));

Це отримує "Виняток UnauthorizedAccess" перевірити це: stackoverflow.com/questions/8877516/…
Ахмед Сабрі

@AhmedSabry: що ви розумієте з цієї помилки.
Трікалдаршіі

Йому потрібен дозвіл на цьому шляху
Ахмед Сабрі

@AhmedSabry точно, ось чому цей 1-лайнер хороший. Якщо всі дозволи хороші, чудово. Якщо ні, то він не вдасться, і вам не потрібні спеціальні власні спроби .. ловити, ви будете знати, яка у вас проблема.
Ofer

Це видає, якщо повний шлях до підкаталогу стає занадто довгим
user2261015,

15
public static long DirSize(DirectoryInfo dir)
{
    return dir.GetFiles().Sum(fi => fi.Length) +
           dir.GetDirectories().Sum(di => DirSize(di));
}

1
Це рішення має декілька проблем, одна з яких полягає у відсутності припинення для рекурсивно симлінкованих каталогів на NTFS (він же Junction Points) та Unix-SMB.
mbx

1
Я згоден. Які інші?
Grozz

2
PathTooLongException(див. цю публікацію в блозі ) і відсутні пам’ятки для читання з певних піддирекцій ( UnauthorizedAccessException). Менш важливою проблемою повинні бути знімні диски (USB-накопичувачі тощо), відключені під час роботи. Обробка винятків тут є обов’язковою - просто поверніть 0 локально та зареєструйте помилки (помилки), якщо підсумований результат повинен мати якесь значення. До речі: застосовано до віддаленого спільного доступу, це може виглядати як атака DOS. Я впевнений, що пропустив хоча б ще один випадок :-)
mbx

Обробляючи ці відомі винятки, я все одно отримую StackOverflowExceptionдля великих дисків.
mbx

2
Я думаю, кидання у всіх цих випадках є прийнятним, і, отже, поведінка за замовчуванням є нормальною. StackOverflowExceptionє єдиним, з яким слід боротися, хоча я не вірю, що до нього можна дійти без рекурсивних символічних посилань.
Grozz

14

Справжнє питання полягає в тому, для чого ви маєте намір використовувати розмір ?

Ваша перша проблема полягає в тому, що існує принаймні чотири визначення поняття "розмір файлу":

  • Зсув "кінця файлу" - це кількість байтів, яку потрібно пропустити, щоб перейти від початку до кінця файлу.
    Іншими словами, це кількість байтів логічно у файлі (з точки зору використання).

  • "Дійсна довжина даних", яка дорівнює зміщенню першого байта, який насправді не зберігається .
    Це завжди менше або дорівнює "кінці файлу" і кратно розміру кластера.
    Наприклад, файл розміром 1 ГБ може мати дійсну довжину даних 1 МБ. Якщо ви попросите Windows прочитати перші 8 МБ, вона прочитає перші 1 МБ і зробить вигляд, що решта даних були там, повертаючи їх як нулі.

  • "Розподілений розмір" файлу. Це завжди більше або дорівнює "кінці файлу".
    Це кількість кластерів, яку ОС виділила для файлу, помножена на розмір кластера.
    На відміну від випадку, коли "кінець файлу" перевищує "допустиму довжину даних", надлишкові байти не вважаються частиною даних файлу, тому ОС не буде заповнювати буфер нулями, якщо ви спробуєте прочитати виділена область після кінця файлу.

  • "Стислий розмір" файлу, який дійсний лише для стиснених (і розріджених?) Файлів.
    Він дорівнює розміру кластера, помноженому на кількість кластерів на томі, які насправді виділено цьому файлу.
    Для файлів, що не стискаються та не розріджуються, немає поняття "стислий розмір"; замість цього ви б використали "виділений розмір".

Ваша друга проблема полягає в тому, що такий "файл" C:\Fooнасправді може мати кілька потоків даних.
Ця назва просто стосується потоку за замовчуванням . Файл може мати альтернативні потоки, наприклад C:\Foo:Bar, розмір яких навіть не відображається в Провіднику!

Ваша третя проблема полягає в тому, що "файл" може мати кілька імен ("жорсткі посилання").
Наприклад, C:\Windows\notepad.exeі C:\Windows\System32\notepad.exeце дві назви для одного і того ж файлу. Будь-яке ім'я можна використовувати для відкриття будь-якого потоку файлу.

Ваша четверта проблема полягає в тому, що "файл" (або каталог) насправді може навіть не бути файлом (або каталогом):
Це може бути м'яке посилання ("символічне посилання" або "точка повторного розбору") на якийсь інший файл ( або каталог).
Цей інший файл може навіть не знаходитися на тому самому диску. Це може навіть вказувати на щось у мережі, або це може бути навіть рекурсивно! Чи повинен бути розмір нескінченним, якщо він рекурсивний?

Ваша п'ята в тому , що є «фільтр» драйвер , які роблять певні файли або каталоги виглядають як реальні файли або каталоги, навіть якщо вони не є. Наприклад, файли зображень WIM від Microsoft (які стискаються) можна "змонтувати" в папці за допомогою інструменту, що називається ImageX, і вони не схожі на точки повторного розбору або посилання. Вони схожі на каталоги - за винятком того, що насправді це не каталоги, і поняття "розмір" для них насправді не має сенсу.

Ваша шоста проблема полягає в тому, що кожен файл вимагає метаданих.
Наприклад, наявність 10 імен для одного і того ж файлу вимагає більше метаданих, що вимагає місця. Якщо імена файлів короткі, наявність 10 імен може коштувати настільки ж дешево, як і 1 ім’я, а якщо вони довгі, то наявність кількох імен може використовувати більше місця на диску для метаданих . (Одна і та ж історія з кількома потоками тощо.)
Чи підраховуєте ви їх теж?


2
Я збентежений. Це не відповідь, це (досить довге) запитання, або його кілька.
Офер Зеліг

9
var size = new DirectoryInfo("E:\\").GetDirectorySize();

і ось код цього методу розширення

public static long GetDirectorySize(this System.IO.DirectoryInfo directoryInfo, bool recursive = true)
{
    var startDirectorySize = default(long);
    if (directoryInfo == null || !directoryInfo.Exists)
        return startDirectorySize; //Return 0 while Directory does not exist.

    //Add size of files in the Current Directory to main size.
    foreach (var fileInfo in directoryInfo.GetFiles())
        System.Threading.Interlocked.Add(ref startDirectorySize, fileInfo.Length);

    if (recursive) //Loop on Sub Direcotries in the Current Directory and Calculate it's files size.
        System.Threading.Tasks.Parallel.ForEach(directoryInfo.GetDirectories(), (subDirectory) =>
    System.Threading.Interlocked.Add(ref startDirectorySize, GetDirectorySize(subDirectory, recursive)));

    return startDirectorySize;  //Return full Size of this Directory.
}

1
Цей код працює швидше, ніж будь-яка відповідь, яка використовує EnumerateFiles () у моєму випадку.
Rm558

6

Здається, наступний метод виконує ваше завдання швидше, ніж рекурсивна функція:

long size = 0;
DirectoryInfo dir = new DirectoryInfo(folder);
foreach (FileInfo fi in dir.GetFiles("*.*", SearchOption.AllDirectories))
{
   size += fi.Length;
}

Простий тест консольної програми показує, що цей цикл підсумовує файли швидше, ніж рекурсивна функція, і забезпечує той самий результат. І ви, мабуть, хочете скористатися методами LINQ (наприклад, Sum ()), щоб скоротити цей код.


У моїх тестах з каталогом, що містить вихідний код та безліч прихованих файлів (каталог svn), результати відрізняються від повідомлень провідника файлової системи.
Девід Думеш

1
як завжди використовувати "*"замість "*.*"для файлів без розширення
Бернхард

5

Швидше! Додати посилання COM "Об'єкт хоста сценарію Windows ..."

public double GetWSHFolderSize(string Fldr)
    {
        //Reference "Windows Script Host Object Model" on the COM tab.
        IWshRuntimeLibrary.FileSystemObject FSO = new     IWshRuntimeLibrary.FileSystemObject();
        double FldrSize = (double)FSO.GetFolder(Fldr).Size;
        Marshal.FinalReleaseComObject(FSO);
        return FldrSize;
    }
private void button1_Click(object sender, EventArgs e)
        {
            string folderPath = @"C:\Windows";
        Stopwatch sWatch = new Stopwatch();

        sWatch.Start();
        double sizeOfDir = GetWSHFolderSize(folderPath);
        sWatch.Stop();
        MessageBox.Show("Directory size in Bytes : " + sizeOfDir + ", Time: " + sWatch.ElapsedMilliseconds.ToString());
          }

ОК добре. Але, схоже, це дає розмір файлів, а не реальний розмір на диску (у мене є випадок, коли розмір становить 18154 байта, а розмір на диску - 163840 байт!)
NGI

5

це рішення працює дуже добре. він збирає всі підпапки:

Directory.GetFiles(@"MainFolderPath", "*", SearchOption.AllDirectories).Sum(t => (new FileInfo(t).Length));

4

До недавнього часу я возився з VS2008 та LINQ, і цей компактний та короткий метод чудово працює для мене (приклад у VB.NET; звичайно, потрібно LINQ / .NET FW 3.5+):

Dim size As Int64 = (From strFile In My.Computer.FileSystem.GetFiles(strFolder, _
              FileIO.SearchOption.SearchAllSubDirectories) _
              Select New System.IO.FileInfo(strFile).Length).Sum()

Коротко кажучи, він здійснює пошук у підкаталогах і його легко зрозуміти, якщо ви знаєте синтаксис LINQ. Ви навіть можете вказати символи підстановки для пошуку конкретних файлів, використовуючи третій параметр функції .GetFiles.

Я не фахівець на C #, але ви можете додати мій простір імен на C # таким чином .

Я думаю, що такий спосіб отримання розміру папки є не тільки коротшим та сучаснішим, ніж спосіб, описаний у посиланні Хао , він в основному використовує той самий метод loop-of-FileInfo, який описаний там в кінці.


C #: повернути Directory.GetFiles (каталог, "*", SearchOption.AllDirectories) .Sum (x => (подвійний) (новий FileInfo (x) .Length));
Томас nn

3
Це не ідеально, оскільки воно зазнає невдачі, якщо до будь-якого каталогу заборонено доступ, і він не може ігнорувати цей виняток.
newman 21.03.13

4

Це найкращий спосіб обчислити розмір каталогу. Тільки інший спосіб все-таки використовував би рекурсію, але був трохи простішим у використанні і не таким гнучким.

float folderSize = 0.0f;
FileInfo[] files = Directory.GetFiles(folder, "*", SearchOption.AllDirectories);
foreach(FileInfo file in files) folderSize += file.Length;

4
Опублікований код не працює, як сказав Джо. Вам потрібно використовувати DirectoryInfo, а не Directory, щоб отримати FileInfoмасив. Також перелік є SearchOption, ні SearchOptions.
Тоні

Ви могли б використовувати Array.ConvertAll<string, FileInfo>(Directory.GetFiles(folder, "*", SearchOption.AllDirectories), x => new FileInfo(x));
PJRobot

4

Я розширив відповідь @ Hao, використовуючи той самий принцип підрахунку, але підтримуючи більш багате повернення даних, так що ви отримаєте розмір назад, рекурсивний розмір, кількість каталогів і кількість рекурсивних каталогів, глибиною N рівнів.

public class DiskSizeUtil
{
    /// <summary>
    /// Calculate disk space usage under <paramref name="root"/>.  If <paramref name="levels"/> is provided, 
    /// then return subdirectory disk usages as well, up to <paramref name="levels"/> levels deep.
    /// If levels is not provided or is 0, return a list with a single element representing the
    /// directory specified by <paramref name="root"/>.
    /// </summary>
    /// <returns></returns>
    public static FolderSizeInfo GetDirectorySize(DirectoryInfo root, int levels = 0)
    {
        var currentDirectory = new FolderSizeInfo();

        // Add file sizes.
        FileInfo[] fis = root.GetFiles();
        currentDirectory.Size = 0;
        foreach (FileInfo fi in fis)
        {
            currentDirectory.Size += fi.Length;
        }

        // Add subdirectory sizes.
        DirectoryInfo[] dis = root.GetDirectories();

        currentDirectory.Path = root;
        currentDirectory.SizeWithChildren = currentDirectory.Size;
        currentDirectory.DirectoryCount = dis.Length;
        currentDirectory.DirectoryCountWithChildren = dis.Length;
        currentDirectory.FileCount = fis.Length;
        currentDirectory.FileCountWithChildren = fis.Length;

        if (levels >= 0)
            currentDirectory.Children = new List<FolderSizeInfo>();

        foreach (DirectoryInfo di in dis)
        {
            var dd = GetDirectorySize(di, levels - 1);
            if (levels >= 0)
                currentDirectory.Children.Add(dd);

            currentDirectory.SizeWithChildren += dd.SizeWithChildren;
            currentDirectory.DirectoryCountWithChildren += dd.DirectoryCountWithChildren;
            currentDirectory.FileCountWithChildren += dd.FileCountWithChildren;
        }

        return currentDirectory;
    }

    public class FolderSizeInfo
    {
        public DirectoryInfo Path { get; set; }
        public long SizeWithChildren { get; set; }
        public long Size { get; set; }
        public int DirectoryCount { get; set; }
        public int DirectoryCountWithChildren { get; set; }
        public int FileCount { get; set; }
        public int FileCountWithChildren { get; set; }
        public List<FolderSizeInfo> Children { get; set; }
    }
}

3
public static long GetDirSize(string path)
{
    try
    {
        return Directory.EnumerateFiles(path).Sum(x => new FileInfo(x).Length)  
            +
               Directory.EnumerateDirectories(path).Sum(x => GetDirSize(x));
    }
    catch
    {
        return 0L;
    }
}

2

Що стосується найкращого алгоритму, ви, мабуть, правильно. Я б порекомендував вам розгадати рекурсивну функцію та використовувати власний стек (пам’ятайте, що переповнення стеку - це кінець світу в програмі .Net 2.0+, виняток не можна зловити IIRC).

Найголовніше, що якщо ви використовуєте його в будь-якій формі інтерфейсу, покладіть його на робочий потік, який сигналізує про потік інтерфейсу із оновленнями.



2

Альтернатива однолінійному рішенню Трікальдарші. (Це дозволяє уникнути необхідності створювати об'єкти FileInfo)

long sizeInBytes = Directory.EnumerateFiles("{path}","*", SearchOption.AllDirectories).Sum(fileInfo => new FileInfo(fileInfo).Length);

змінна fileInfo має тип рядка, а не FileInfo.
user425678

2
Directory.GetFiles(@"C:\Users\AliBayat","*",SearchOption.AllDirectories)
.Select (d => new FileInfo(d))
.Select (d => new { Directory = d.DirectoryName,FileSize = d.Length} )
.ToLookup (d => d.Directory )
.Select (d => new { Directory = d.Key,TotalSizeInMB =Math.Round(d.Select (x =>x.FileSize)
.Sum () /Math.Pow(1024.0,2),2)})
.OrderByDescending (d => d.TotalSizeInMB).ToList();

Виклик GetFilesіз SearchOption.AllDirectoriesфункцією повертає повне ім'я всіх файлів у всіх subdirectoriesзазначених каталогах. ОС відображає розмір файлів у байтах. Ви можете отримати розмір файлу з його властивості Length. Поділивши його на 1024, піднятий до рівня 2, ви отримаєте розмір файлу в мегабайтах. Оскільки каталог / папка може містити багато файлів, d.Select(x => x.FileSize)повертає колекцію розмірів файлів, виміряних у мегабайтах. Останній дзвінок доSum() знаходження загального розміру файлів у вказаному каталозі.

Оновлення: filterMask = " . " Не працює з файлами без розширення


1

Найшвидший спосіб, який я придумав, - це використання EnumerateFiles з SearchOption.AllDirectories. Цей метод також дозволяє оновлювати інтерфейс, переглядаючи файли та підраховуючи розмір. Довгі імена шляхів не створюють проблем, оскільки FileInfo або DirectoryInfo не намагаються створити для імені довгого шляху. Під час перерахування файлів, незважаючи на те, що ім'я файлу довге, FileInfo, повернутий EnumerateFiles, не створює проблем, якщо ім'я початкового каталогу не надто довге. Проблема з UnauthorizedAccess все ще існує.

    private void DirectoryCountEnumTest(string sourceDirName)
    {
        // Get the subdirectories for the specified directory.
        long dataSize = 0;
        long fileCount = 0;
        string prevText = richTextBox1.Text;

        if (Directory.Exists(sourceDirName))
        {
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            foreach (FileInfo file in dir.EnumerateFiles("*", SearchOption.AllDirectories))
            {
                fileCount++;
                try
                {
                    dataSize += file.Length;
                    richTextBox1.Text = prevText + ("\nCounting size: " + dataSize.ToString());
                }
                catch (Exception e)
                {
                    richTextBox1.AppendText("\n" + e.Message);
                }
            }
            richTextBox1.AppendText("\n files:" + fileCount.ToString());
        }
    }

1

Цей основний додаток командного рядка .NET тут обчислює розміри каталогів для заданого шляху:

https://github.com/garethrbrown/folder-size

Ключовим методом є цей, який рекурсивно перевіряє підкаталоги, щоб отримати загальний розмір.

private static long DirectorySize(SortDirection sortDirection, DirectoryInfo directoryInfo, DirectoryData directoryData)
{
        long directorySizeBytes = 0;

        // Add file sizes for current directory

        FileInfo[] fileInfos = directoryInfo.GetFiles();

        foreach (FileInfo fileInfo in fileInfos)
        {
            directorySizeBytes += fileInfo.Length;
        }

        directoryData.Name = directoryInfo.Name;

        directoryData.SizeBytes += directorySizeBytes;

        // Recursively add subdirectory sizes

        DirectoryInfo[] subDirectories = directoryInfo.GetDirectories();

        foreach (DirectoryInfo di in subDirectories)
        {
            var subDirectoryData = new DirectoryData(sortDirection);

            directoryData.DirectoryDatas.Add(subDirectoryData);

            directorySizeBytes += DirectorySize(sortDirection, di, subDirectoryData);
        }

        directoryData.SizeBytes = directorySizeBytes;

        return directorySizeBytes;
    }
}

1

Приклад декількох потоків для обчислення розміру каталогу з Microsoft Docs , що було б швидше

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      long totalSize = 0;

      String[] args = Environment.GetCommandLineArgs();
      if (args.Length == 1) {
         Console.WriteLine("There are no command line arguments.");
         return;
      }
      if (! Directory.Exists(args[1])) {
         Console.WriteLine("The directory does not exist.");
         return;
      }

      String[] files = Directory.GetFiles(args[1]);
      Parallel.For(0, files.Length,
                   index => { FileInfo fi = new FileInfo(files[index]);
                              long size = fi.Length;
                              Interlocked.Add(ref totalSize, size);
                   } );
      Console.WriteLine("Directory '{0}':", args[1]);
      Console.WriteLine("{0:N0} files, {1:N0} bytes", files.Length, totalSize);
   }
}
// The example displaysoutput like the following:
//       Directory 'c:\windows\':
//       32 files, 6,587,222 bytes

Цей приклад обчислює лише файли в поточній папці, тому, якщо ви хочете обчислити всі файли рекурсивно, ви можете змінити файл

String[] files = Directory.GetFiles(args[1]);

до

String[] files = Directory.GetFiles(args[1], "*", SearchOption.AllDirectories);


0

Я намагаюся змінити зразок (Олександр Пепін та відповідь Хао)

Як є

    private long GetDirectorySize(string dirPath)
    {
        if (Directory.Exists(dirPath) == false)
        {
            return 0;
        }

        DirectoryInfo dirInfo = new DirectoryInfo(dirPath);

        long size = 0;

        // Add file sizes.
        FileInfo[] fis = dirInfo.GetFiles();
        foreach (FileInfo fi in fis)
        {
            size += fi.Length;
        }

        // Add subdirectory sizes.
        DirectoryInfo[] dis = dirInfo.GetDirectories();
        foreach (DirectoryInfo di in dis)
        {
            size += GetDirectorySize(di.FullName);
        }

        return size;
    }

Бути

    private long GetDirectorySize2(string dirPath)
    {
        if (Directory.Exists(dirPath) == false)
        {
            return 0;
        }

        DirectoryInfo dirInfo = new DirectoryInfo(dirPath);

        long size = 0;

        // Add file sizes.
        IEnumerable<FileInfo> fis = dirInfo.EnumerateFiles("*.*", SearchOption.AllDirectories);
        foreach (FileInfo fi in fis)
        {
            size += fi.Length;
        }

        return size;
    }

нарешті ви можете перевірити результат

        // ---------------------------------------------
        // size of directory
        using System.IO;

        string log1Path = @"D:\SampleDirPath1";
        string log2Path = @"D:\SampleDirPath2";
        string log1DirName = Path.GetDirectoryName(log1Path);
        string log2DirName = Path.GetDirectoryName(log2Path);
        long log1Size = GetDirectorySize(log1Path);
        long log2Size = GetDirectorySize(log2Path);
        long log1Size2 = GetDirectorySize2(log1Path);
        long log2Size2 = GetDirectorySize2(log2Path);

        Console.WriteLine($@"{log1DirName} Size: {SizeSuffix(log1Size)}, {SizeSuffix(log1Size2)}
        {log2DirName} Size: {SizeSuffix(log2Size)}, {SizeSuffix(log2Size2)}");

а це функція SizeSuffix

    private static readonly string[] SizeSuffixes =
               { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

    /// <summary>
    /// Size Display
    /// </summary>
    /// <param name="value">bytes 數值</param>
    /// <param name="decimalPlaces">小數位數</param>
    /// <returns></returns>
    public static string SizeSuffix(Int64 value, int decimalPlaces = 2)
    {
        if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); }
        if (value < 0) { return "-" + SizeSuffix(-value); }
        if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); }

        // mag is 0 for bytes, 1 for KB, 2, for MB, etc.
        int mag = (int)Math.Log(value, 1024);

        // 1L << (mag * 10) == 2 ^ (10 * mag) 
        // [i.e. the number of bytes in the unit corresponding to mag]
        decimal adjustedSize = (decimal)value / (1L << (mag * 10));

        // make adjustment when the value is large enough that
        // it would round up to 1000 or more
        if (Math.Round(adjustedSize, decimalPlaces) >= 1000)
        {
            mag += 1;
            adjustedSize /= 1024;
        }

        return string.Format("{0:n" + decimalPlaces + "} {1}",
            adjustedSize,
            SizeSuffixes[mag]);
    }

-3

Я знаю, що це не рішення .net, але воно все одно приходить. Можливо, це стане в нагоді людям, які мають Windows 10 і хочуть швидшого рішення. Наприклад, якщо ви запустите цю команду в командному рядку або натиснувши winKey + R:

bash -c "du -sh /mnt/c/Users/; sleep 5"    

Це sleep 5так, що ви встигли побачити результати, а вікна не закриваються

На моєму комп’ютері, що відображає:

введіть тут опис зображення

Зверніть увагу в кінці, як він показує 85G (85 гігабайт). Це швидко вечеря в порівнянні з тим, що робити з .Net. Якщо ви хочете побачити розмір точніше, видалітьh що означає людину читабельним.

Тож просто зробіть щось на зразок Processes.Start("bash",... arguments)Це не точний код, але ви зрозуміли ідею.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.