none
Größe eines Verzeichnisses anzeigen [C# - WindowsForms] RRS feed

  • Frage

  • Hallo,

    Habe etwas programmiert was die Größe von einem File ausgiebt.
    Nun möchte ich auch die Größe eines ganzen Ordners herauslesen. Wie funktioniert das?

    Was ich bereits habe:

    Verwende:
    1 Textbox für eingabe des Pfades(Txt_Start), 1 Textbox für Ausgabe der Größe des Files (textBox_1)
    1 Button der bei drücken die Größe des Files ausgiebt. (Sichern)

    Code:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Auslesen
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Sichern_Click(object sender, EventArgs e)
            {
               
                string path = this.Txt_Start.Text;
    
               
                System.IO.FileInfo info = new System.IO.FileInfo(path);
                long size_in_bytes = info.Length;
    
                
                System.IFormatProvider provider = System.Globalization.CultureInfo.InvariantCulture;
                string size_str = size_in_bytes.ToString(provider);
    
                
                this.textBox1.Text = size_str;
            }
        }
    }
    

    Freue mich über jede Antwort! :)

    Sonntag, 14. Juni 2015 18:43

Antworten

  • Hallo,
    meines Wissens nach gibt es keine Methode um direkt auf die größe eines Verzeichnisses zu kommen. Du musst wohl oder übel die Dateien + die Unterverzeichnisse durchlaufen.

    Hier bietet sich eine Rekursion an:

    public long CalculateDirectorySize(DirectoryInfo startDirectory, bool includeSubDirectories = false) {
      long sizeInBytes = startDirectory.GetFiles().Sum(t => t.Length);
    
      if(includeSubDirectories) {
      foreach(var directory in startDirectory.GetDirectories()) {
          sizeInBytes += CalculateDirectorySize(directory, includeSubDirectories);
        }
      }
      return sizeInBytes;
    }

    Damit geht es. Ich hoffe ich konnte dir Helfen :)


    Viele Grüße Holger M. Rößler


    Sonntag, 14. Juni 2015 19:07
  • Hallo Michael,

    wenn du die größe eines ganzen Ordner haben möchtest, musst du eigentlich rekursiv ALLE im Ordner vorhandenne Dteien auflisten und deren größe Addieren.

    Du kannst z.B. folgenden Funktion verwenden:

    // DirectoryInfo in System.IO
    
    static ulong GetDirectorySize(DirectoryInfo dir) {
      ulong sum = 0; 
      // Die Summe der Datenlänge von Daten
      // aus diesem Ordner
      
      // Länge aller Dateien bestimmen
      foreach (var file in dir.GetFiles()) {
         // Dateilänge hinzufügen
         sum += (ulong)file.Length;
      }
      
      // rekursiver Aufruf
      foreach (var dir1 in dir.GetDirectories()) {
         sum += GetDirectorySize(dir1); 
      }
      
      return sum;
    }

    Du musst da nur auf zwei Sachen aufpassen:

    1. Pass auf, dass der Zähler (sum) nicht überläuft, sonst gibt es eine falsche Zahl
    2. Sollte auf einen Ordner/eine Datei nicht zugegriffen werden können (fehlende Rechte), so schlägt die gesamte Funktion fehl
    3.   -> Lösung zu (2) Den Ordnerzugriff und den Dateizugriff in eine Try-Catch-Anweisung packen. Sollte ein Fehler geworfen werden, irgendwo einfach dies zwischenspeichern und beim anzeigen der Größe dazuschreiben: Ungefähre Dateigröße. Den Fehler einfach verwerfen/ignorieren.

    PS: Der Aufruf würde wie folgt laufen:

    ulong sum = GetDirectorySize(new DirectoryInfo("C:\\Windows"));
    MessageBox.Show("Größe: " + sum + " Bytes");
    // Du kannst auch die Bytes in MB oder GB umwandeln, wie du es möchtest

    Ich hoffe ich konnte dir etwas helfen,


    © 2015 Thomas Roskop

    Germany // Deutschland

    • Als Antwort markiert Michael.5 Sonntag, 14. Juni 2015 19:36
    Sonntag, 14. Juni 2015 19:19

Alle Antworten

  • Hallo,
    meines Wissens nach gibt es keine Methode um direkt auf die größe eines Verzeichnisses zu kommen. Du musst wohl oder übel die Dateien + die Unterverzeichnisse durchlaufen.

    Hier bietet sich eine Rekursion an:

    public long CalculateDirectorySize(DirectoryInfo startDirectory, bool includeSubDirectories = false) {
      long sizeInBytes = startDirectory.GetFiles().Sum(t => t.Length);
    
      if(includeSubDirectories) {
      foreach(var directory in startDirectory.GetDirectories()) {
          sizeInBytes += CalculateDirectorySize(directory, includeSubDirectories);
        }
      }
      return sizeInBytes;
    }

    Damit geht es. Ich hoffe ich konnte dir Helfen :)


    Viele Grüße Holger M. Rößler


    Sonntag, 14. Juni 2015 19:07
  • Hallo Michael,

    wenn du die größe eines ganzen Ordner haben möchtest, musst du eigentlich rekursiv ALLE im Ordner vorhandenne Dteien auflisten und deren größe Addieren.

    Du kannst z.B. folgenden Funktion verwenden:

    // DirectoryInfo in System.IO
    
    static ulong GetDirectorySize(DirectoryInfo dir) {
      ulong sum = 0; 
      // Die Summe der Datenlänge von Daten
      // aus diesem Ordner
      
      // Länge aller Dateien bestimmen
      foreach (var file in dir.GetFiles()) {
         // Dateilänge hinzufügen
         sum += (ulong)file.Length;
      }
      
      // rekursiver Aufruf
      foreach (var dir1 in dir.GetDirectories()) {
         sum += GetDirectorySize(dir1); 
      }
      
      return sum;
    }

    Du musst da nur auf zwei Sachen aufpassen:

    1. Pass auf, dass der Zähler (sum) nicht überläuft, sonst gibt es eine falsche Zahl
    2. Sollte auf einen Ordner/eine Datei nicht zugegriffen werden können (fehlende Rechte), so schlägt die gesamte Funktion fehl
    3.   -> Lösung zu (2) Den Ordnerzugriff und den Dateizugriff in eine Try-Catch-Anweisung packen. Sollte ein Fehler geworfen werden, irgendwo einfach dies zwischenspeichern und beim anzeigen der Größe dazuschreiben: Ungefähre Dateigröße. Den Fehler einfach verwerfen/ignorieren.

    PS: Der Aufruf würde wie folgt laufen:

    ulong sum = GetDirectorySize(new DirectoryInfo("C:\\Windows"));
    MessageBox.Show("Größe: " + sum + " Bytes");
    // Du kannst auch die Bytes in MB oder GB umwandeln, wie du es möchtest

    Ich hoffe ich konnte dir etwas helfen,


    © 2015 Thomas Roskop

    Germany // Deutschland

    • Als Antwort markiert Michael.5 Sonntag, 14. Juni 2015 19:36
    Sonntag, 14. Juni 2015 19:19
  • Ok, es funktioniert!

    Vielen Dank Thomas :-)

    Sonntag, 14. Juni 2015 19:25
  • Perfekt! Das freut mich doch sehr!

    Vielleicht könntest du meine Antwort als Antwort markieren (unter den Antworten sollte bei dir irgendwo als Antwort markieren stehen, einfach clicken!), damit auch andere die Antwort sehen ;)

    Danke

    @Holger: Dein Code hat einen Fehler. Es steht bei dir:

    return sizeInBytes + CalculateDirectorySize(directory, includeSubDirectories);

    Das würde dazu führen, dass der Code genau den ersten Ordenr sucht und durchläuft und dann direkt abbricht, also den zweiten und dritten Ordern nicht mitnimmt.


    © 2015 Thomas Roskop

    Germany // Deutschland


    • Bearbeitet Thomas Roskop Sonntag, 14. Juni 2015 19:30 Anmekrungen zu Holger
    Sonntag, 14. Juni 2015 19:28
  • Klar, schon gemacht!

    Du hast mir den Tag gerettet. :)


    • Bearbeitet Michael.5 Sonntag, 14. Juni 2015 19:38
    Sonntag, 14. Juni 2015 19:37
  • Hallo Thomas,
    bei mir hat der Code die Rekurion 1a durchlaufen.

    Und mal wieder verstehe ich nicht warum meine Antwort nicht als Antwort markiert wurde. Welchen Teil der Frage habe ich nicht beantwortet! Das geht jetzt schon die ganze Zeit so. Zumal meine Antwort auch die erste war!

    Es kotzt mich langsam an! Dafür muss ich mich Sonntags nicht hinsetzen und die Fragen der User beantworten!!


    Viele Grüße Holger M. Rößler





    Sonntag, 14. Juni 2015 21:01
  • Hallo zusammen,

    ich stimme Holger zu, dass sein Code genauso gut funktioniert wie der von Thomas. Auch enthält er meiner Meinung nach keinen Fehler. Auch verstehe ich die von ihm angesprochene Problematik das einige gute Antworten nicht wirklich honoriert werden - da rede ich auch aus Erfahrung.

    @Michael
    Hat es einen bestimmten Grund warum du nur Thomas Post als Antwort markiert hast? Du kannst hier im Forum auch mehrere Antworten markieren.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Sonntag, 14. Juni 2015 22:39
    Moderator
  • Hallo Tom,
    ich bedaure, dass du die gleiche Erfahrung machen musstest. Das ist in der Regel nicht so wild, aber in letzter Zeit nimmt es absolut überhand.

    Und was mich besonders nervt: Dass Beantworter die Benutzer dazu drängen ihre Antworten als Antwort zu markieren. Das sollte nicht erlaubt sein. Auch das nimmt leider überhand. Denn das ist doch die Entscheidung des Nutzers und nicht des Beantworters.

    Und der Gipfel ist noch, wenn dein Code öffentlich und auch noch zu Unrecht schlecht geredet wird. Und das von jemand der es besser wissen könnte und der es nicht mal getestet hat. Das empfinde ich als absolut unkollegial und lässt jedwedes Fingerspitzengefühl für ein öffentliches Forum vermissen.

    Das sind 2 Dinge, die mich in letzter Zeit extermst ärgern, da es viele Beantworter einfach um Ihren "Lohn" bringt. Du selbst hast die Erfahrung ja auch gemacht.


    Viele Grüße Holger M. Rößler


    Montag, 15. Juni 2015 00:58
  •  @Thomas
     Der Code von Holger enthält tatsächlich einen kleinen Fehler, es müssten die Ordner aufsummiert werden, statt dort direkt ein Return stehen zu haben.

    @Holger
    Den Frust darüber kann ich gut verstehen, leider wird der eigenen Beitrag nicht immer honoriert. Das betteln um die Markierung als Antwort empfinde ich auch nicht als besonders positiv.
    Positiv aufgefallen ist mir allerdings die Zunahme der "Hilfreich"-Bewertungen, insbesondere auch deshalb, weil eben nicht immer die sinnvollste Antwort als "Antwort" markiert wird. Ich finde die "Hilfreich"-Bewertungen hier oder in ähnlicher Form in anderen Foren oft nützlicher als die "Antwort"-Markierung.
    Ich hoffe Du bleibst uns hier erhalten, den dieses Forum kann Antworten von guter Qualität brauchen.

    Gruß


    - Florian


    • Bearbeitet Florian Haupt Montag, 15. Juni 2015 11:15 Falsche Aussage revidiert
    Montag, 15. Juni 2015 07:31
  • Hallo,

    ich habe mal einen Code erstellt, der sowohl meine Antwort als auch die von Holger beinhaltet.

    Den kompletten Code einschließlich Beispiel-Order (mit mehreren Unterordnern) findet ihr hier: http://1drv.ms/1GnCyBK

    Das System zeigt mir als Größe ~9600000 Bytes (9,6MB) an.

        Mein Algorithmus:      9529664 Bytes
        Holger's Algorithmus:  1191208 Bytes

    Jetzt sollte damit die Frage nach der Korrektheit meiner Anmerkung beantwortet sein.


    __________________________________________________

    Kommen wir jetzt zu den anderen Kritikpunkten.

    Das System mit den "Als Antwort markieren" mit den dazu passenden Punkten ist ja als Motivation eingerichtet worden.

    Natürlich ist es schade, wenn die eigene Antwort nicht markiert wurde aber daraus jetzt eine solche Diskussion zu starten ist doch nun wirklich übertrieben.
    Natürlich kenn ich es, dass auch meine Antworten nicht markiert wurden; da kann man natürlich höflich nachfragen.
    Vor allem, da zu bedenken ist, dass der Fragesteller (Michael.5) erst seit kurzem dabei ist (siehe sein Profil: https://social.msdn.microsoft.com/profile/michael.5/?ws=usercard-mini ). Deshalb hätte es ja sein können, dass er es nicht weiß - wo in den anderen Forum solch ein System auch nicht immer vorherrscht. Und aus diesem Grunde habe ich ihn informiert.
    Insofern kann man es doch nicht als betteln bezeichnen.

    Und mir zu unterstellen ich hätte Holger bzw. seine Antwort "schlecht geredet" ist doch unhaltbar.
    Selbst wenn ich mich geirrt hätte, dann könnte man doch kurz Bescheid geben und das Problem wäre gelöst.

    Es tut mir leid, solltest du dich persönlich angegriffen gefühlt haben. Zugegeben, die Art und Weise mich auf deinen Code zu beziehen ist nicht die galanteste gewesen. Aber die Antwort war auch nicht sehr passend...

    Ich hoffe inständig, dass damit diese nutzlose und unsinnige Diskussion geschlossen werden kann.
    Schließlich sind wir hier nicht im Forum um uns die Köpfe einzuschlagen sondern um anderen zu helfen.


    © 2015 Thomas Roskop

    Germany // Deutschland

    Montag, 15. Juni 2015 10:28
  • Hallo,

    Thomas Roskop hat recht, der Code von Holger ist nicht ganz korrekt.

    Grüße

    Montag, 15. Juni 2015 10:43
  • Hallo,

    Ich habe Thomas’ Beispiel heruntergeladen und getestet.

     @Thomas
     Der Code von Holger enthält tatsächlich einen kleinen Fehler, es müssten die Ordner aufsummiert werden, statt dort direkt ein Return stehen zu haben.

    Unter Berücksichtigung dieser Bemerkung habe ich die Zeile, wo return zum ersten Mal vorkommt, leicht angepasst:

          sizeInBytes += CalculateDirectorySize(directory, includeSubDirectories);
          //anstatt: return sizeInBytes + CalculateDirectorySize(directory, includeSubDirectories);
    

    Dadurch funktioniert auch diese Variante korrekt. Da ich vermeiden möchte, auf Nicht als Antwort vorschlagen zu klicken und eine zweite Vorgehensweise künftigen Lesern dieses Threads nützlich sein wird, wie wäre es, wenn diese Zeile entsprechend geändert wird, wenn es keine Einwände gibt (und dann der Beitrag entweder vom Thread-Ersteller oder von einem Moderator (wenn der TE nicht zurückkehrt) als Antwort markiert wird)?

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Montag, 15. Juni 2015 12:21
    Administrator
  • Hallo zusammen,

    erstmal möchte ich mich entschuldigen - jetzt sehe auch ich den Fehler in Holgers Code. War vielleicht doch schon zu spät.

    Hilfreich bewerten vs. als Antwort markieren
    Innerhalb des Forums mag ich die als Hilfreich bewerten Funktion auch. Trotzdem rücken die als Antwort markierten Posts mehr in den Vordergrund. Einmal durch die spezielle Markierung aber beispielsweise auch in den MVP Profilen. (Beispielsweise meines)


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Montag, 15. Juni 2015 13:24
    Moderator
  • Schön, dass jetzt wohl scheinbar eine friedliche Lösung gefunden wurde.


    © 2015 Thomas Roskop

    Germany // Deutschland

    Montag, 15. Juni 2015 14:01