Gewusst wie: Abfragen der Gesamtzahl an Bytes in einem Ordnersatz (LINQ)

Aktualisiert: November 2007

Mit diesem Beispiel wird veranschaulicht, wie die Gesamtanzahl an Bytes abgerufen wird, die von allen Dateien in einem angegebenen Ordner und allen Unterordnern verwendet werden.

Beispiel

Die Sum-Methode fügt die Werte aller ausgewählten Elemente in der select-Klausel hinzu. Sie können diese Abfrage leicht so ändern, dass die größte oder die kleinste Datei in der angegebenen Verzeichnisstruktur abgerufen wird, indem Sie statt Sum die Min-Methode oder die Max-Methode aufrufen.

Module QueryTotalBytes
    Sub Main()

        ' Change the drive\path if necessary.
        Dim root As String = "C:\Program Files\Microsoft Visual Studio 9.0\VB"

        'Take a snapshot of the folder contents.
        ' This method assumes that the application has discovery permissions
        ' for all folders under the specified path.
        Dim fileList = My.Computer.FileSystem.GetFiles _
                  (root, FileIO.SearchOption.SearchAllSubDirectories, "*.*")

        Dim fileQuery = From file In fileList _
                        Select GetFileLength(file)

        ' Force execution and cache the results to avoid multiple trips to the file system.
        Dim fileLengths = fileQuery.ToArray()

        ' Find the largest file
        Dim maxSize = Aggregate aFile In fileLengths Into Max()

        ' Find the total number of bytes
        Dim totalBytes = Aggregate aFile In fileLengths Into Sum()

        Console.WriteLine("The largest file is " & maxSize & " bytes")
        Console.WriteLine("There are " & totalBytes & " total bytes in " & _
                          fileList.Count & " files under " & root)

        ' Keep the console window open in debug mode
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub

    ' This method is used to catch the possible exception
    ' that can be raised when accessing the FileInfo.Length property.
    Function GetFileLength(ByVal filename As String) As Long
        Dim retval As Long
        Try
            Dim fi As New System.IO.FileInfo(filename)
            retval = fi.Length
        Catch ex As System.IO.FileNotFoundException
            ' If a file is no longer present,
            ' just return zero bytes. 
            retval = 0
        End Try

        Return retval
    End Function
End Module
class QuerySize
{
    public static void Main()
    {
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\VC#";

        // Take a snapshot of the file system.
        // This method assumes that the application has discovery permissions
        // for all folders under the specified path.
        IEnumerable<string> fileList = System.IO.Directory.GetFiles(startFolder, "*.*", System.IO.SearchOption.AllDirectories);

        var fileQuery = from file in fileList
                        select GetFileLength(file);

        // Cache the results to avoid multiple trips to the file system.
        long[] fileLengths = fileQuery.ToArray();

        // Return the size of the largest file
        long largestFile = fileLengths.Max();

        // Return the total number of bytes in all the files under the specified folder.
        long totalBytes = fileLengths.Sum();

        Console.WriteLine("There are {0} bytes in {1} files under {2}",
            totalBytes, fileList.Count(), startFolder);
        Console.WriteLine("The largest files is {0} bytes.", largestFile);

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

    // This method is used to swallow the possible exception
    // that can be raised when accessing the System.IO.FileInfo.Length property.
    static long GetFileLength(string filename)
    {
        long retval;
        try
        {
            System.IO.FileInfo fi = new System.IO.FileInfo(filename);
            retval = fi.Length;
        }
        catch (System.IO.FileNotFoundException)
        {
            // If a file is no longer present,
            // just add zero bytes to the total.
            retval = 0;
        }
        return retval;
    }
}

Wenn Sie nur die Anzahl an Bytes in einer angegebenen Verzeichnisstruktur zählen müssen, können Sie dies effizienter ohne die Erstellung einer LINQ-Abfrage erledigen, denn durch das Erstellen der Listenauflistung wird ein Mehraufwand verursacht. Die Nützlichkeit der LINQ-Methode erhöht sich, wenn die Abfrage komplexer wird oder wenn Sie mehrere Abfragen für dieselbe Datenquelle ausführen müssen.

Die Abfrage ruft eine separate Methode auf, um die Dateilänge abzufragen. Der Grund dafür ist, dass ein mögliche Ausnahme abgefangen werden soll, die ausgelöst wird, wenn die Datei auf einem anderen Thread gelöscht wurde, nachdem das FileInfo-Objekt im Aufruf von GetFiles erstellt wurde. Selbst wenn das FileInfo-Objekt bereits erstellt wurde, kann die Ausnahme auftreten, da ein FileInfo-Objekt versuchen wird, seine Length-Eigenschaft mit der aktuellen Länge zu aktualisieren, wenn erstmalig auf die Eigenschaft zugegriffen wird. Indem diese Operation in einen try-catch-Block außerhalb der Abfrage gesetzt wird, folgt der Code der Regel, Operationen, die Nebeneffekte verursachen können, in Abfragen zu vermeiden. Im Allgemeinen muss größte Sorgfalt an den Tag gelegt werden, wenn Ausnahmen verwendet werden, um sicherzustellen, dass eine Anwendung nicht in einem unbekannten Zustand gelassen wird.

Kompilieren des Codes

  • Erstellen Sie ein Visual Studio-Projekt, das die .NET Framework-Version 3.5 zum Ziel hat. Das Projekt weist standardmäßig einen Verweis auf System.Core.dll und eine using-Direktive (C#) oder eine Imports-Anweisung (Visual Basic) für den System.Linq-Namespace auf. Fügen Sie in C#-Projekten eine using-Direktive für den System.IO-Namespace hinzu.

  • Kopieren Sie diesen Code ins Projekt.

  • Drücken Sie F5, um das Programm zu kompilieren und auszuführen.

  • Drücken Sie eine beliebige Taste, um das Konsolenfenster zu schließen.

Robuste Programmierung

Für umfassende Abfrageoperationen über die Inhalte mehrerer Arten von Dokumenten und Dateien empfiehlt es sich, das Modul Windows Desktop Search zu verwenden.

Siehe auch

Konzepte

LINQ to Objects

LINQ und Dateiverzeichnisse