Freigeben über


Gewusst wie: Abfragen der größten Datei oder der größten Dateien in einer Verzeichnisstruktur (LINQ)

Dieses Beispiel zeigt fünf Abfragen in Bezug auf die Dateigröße in Bytes.

  • So rufen Sie die Größe in Bytes der größten Datei ab.

  • So rufen Sie die Größe in Bytes der kleinsten Datei ab.

  • So rufen Sie das FileInfo-Objekt der größten oder kleinsten Datei in einem oder mehreren Ordnern unter einem angegebenen Stammordner auf

  • So rufen Sie eine Sequenz, zum Beispiel die 10 größten Dateien, ab

  • So ordnen Sie Dateien in Gruppen nach ihrer Dateigröße in Bytes, unter Auslassung der Dateien, die kleiner als eine angegebene Größe sind

Beispiel

Das folgende Beispiel enthält fünf separate Abfragen, die zeigen, wie Dateien, abhängig von ihrer Dateigröße in Bytes, abgefragt und gruppiert werden. Sie können diese Beispiele ganz leicht abändern, um bei der Abfrage eine andere Eigenschaft des FileInfo-Objekts zu berücksichtigen.

Module QueryBySize
    Sub Main()

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

        'Take a snapshot of the folder contents
        Dim dir As New System.IO.DirectoryInfo(root)
        Dim fileList = dir.GetFiles("*.*", System.IO.SearchOption.AllDirectories)

        ' Return the size of the largest file
        Dim maxSize = Aggregate aFile In fileList Into Max(GetFileLength(aFile))

        'Dim maxSize = fileLengths.Max
        Console.WriteLine("The length of the largest file under {0} is {1}", _
                          root, maxSize)

        ' Return the FileInfo object of the largest file
        ' by sorting and selecting from the beginning of the list
        Dim filesByLengDesc = From file In fileList _
                              Let filelength = GetFileLength(file) _
                              Where filelength > 0 _
                              Order By filelength Descending _
                              Select file

        Dim longestFile = filesByLengDesc.First

        Console.WriteLine("The largest file under {0} is {1} with a length of {2} bytes", _
                          root, longestFile.FullName, longestFile.Length)

        Dim smallestFile = filesByLengDesc.Last

        Console.WriteLine("The smallest file under {0} is {1} with a length of {2} bytes", _
                                root, smallestFile.FullName, smallestFile.Length)

        ' Return the FileInfos for the 10 largest files
        ' Based on a previous query, but nothing is executed
        ' until the For Each statement below.
        Dim tenLargest = From file In filesByLengDesc Take 10

        Console.WriteLine("The 10 largest files under {0} are:", root)

        For Each fi As System.IO.FileInfo In tenLargest
            Console.WriteLine("{0}: {1} bytes", fi.FullName, fi.Length)
        Next

        ' Group files according to their size,
        ' leaving out the ones under 200K
        Dim sizeGroups = From file As System.IO.FileInfo In fileList _
                         Where file.Length > 0 _
                         Let groupLength = file.Length / 100000 _
                         Group file By groupLength Into fileGroup = Group _
                         Where groupLength >= 2 _
                         Order By groupLength Descending

        For Each group In sizeGroups
            Console.WriteLine(group.groupLength + "00000")

            For Each item As System.IO.FileInfo In group.fileGroup
                Console.WriteLine("   {0}: {1}", item.Name, item.Length)
            Next
        Next

        ' 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.
    ' In this particular case, it is safe to ignore the exception.
    Function GetFileLength(ByVal fi As System.IO.FileInfo) As Long
        Dim retval As Long
        Try
            retval = fi.Length
        Catch ex As FileNotFoundException
            ' If a file is no longer present,
            ' just return zero bytes. 
            retval = 0
        End Try

        Return retval
    End Function
End Module
class QueryBySize
{
    static void Main(string[] args)
    {
        QueryFilesBySize();
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    private static void QueryFilesBySize()
    {
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\";

        // Take a snapshot of the file system.
        System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(startFolder);

        // This method assumes that the application has discovery permissions
        // for all folders under the specified path.
        IEnumerable<System.IO.FileInfo> fileList = dir.GetFiles("*.*", System.IO.SearchOption.AllDirectories);

        //Return the size of the largest file
        long maxSize =
            (from file in fileList
             let len = GetFileLength(file)
             select len)
             .Max();

        Console.WriteLine("The length of the largest file under {0} is {1}",
            startFolder, maxSize);

        // Return the FileInfo object for the largest file
        // by sorting and selecting from beginning of list
        System.IO.FileInfo longestFile =
            (from file in fileList
             let len = GetFileLength(file)
             where len > 0
             orderby len descending
             select file)
            .First();

        Console.WriteLine("The largest file under {0} is {1} with a length of {2} bytes",
                            startFolder, longestFile.FullName, longestFile.Length);

        //Return the FileInfo of the smallest file
        System.IO.FileInfo smallestFile =
            (from file in fileList
             let len = GetFileLength(file)
             where len > 0
             orderby len ascending
             select file).First();

        Console.WriteLine("The smallest file under {0} is {1} with a length of {2} bytes",
                            startFolder, smallestFile.FullName, smallestFile.Length);

        //Return the FileInfos for the 10 largest files
        // queryTenLargest is an IEnumerable<System.IO.FileInfo>
        var queryTenLargest =
            (from file in fileList
             let len = GetFileLength(file)
             orderby len descending
             select file).Take(10);

        Console.WriteLine("The 10 largest files under {0} are:", startFolder);

        foreach (var v in queryTenLargest)
        {
            Console.WriteLine("{0}: {1} bytes", v.FullName, v.Length);
        }


        // Group the files according to their size, leaving out
        // files that are less than 200000 bytes. 
        var querySizeGroups =
            from file in fileList
            let len = GetFileLength(file)
            where len > 0
            group file by (len / 100000) into fileGroup
            where fileGroup.Key >= 2
            orderby fileGroup.Key descending
            select fileGroup;


        foreach (var filegroup in querySizeGroups)
        {
            Console.WriteLine(filegroup.Key.ToString() + "00000");
            foreach (var item in filegroup)
            {
                Console.WriteLine("\t{0}: {1}", item.Name, item.Length);
            }
        }
    }

    // This method is used to swallow the possible exception
    // that can be raised when accessing the FileInfo.Length property.
    // In this particular case, it is safe to swallow the exception.
    static long GetFileLength(System.IO.FileInfo fi)
    {
        long retval;
        try
        {
            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;
    }

}

Um ein oder mehrere vollständige FileInfo-Objekte zurückzugeben, muss die Abfrage zuerst jedes einzelne Objekt in der Datenquelle untersuchen und sie dann nach dem Wert ihrer Length-Eigenschaft sortieren. Anschließend kann das einzelne Objekt oder die Sequenz mit den größten Längen zurückgegeben werden. Verwenden Sie First, um das erste Element in einer Liste zurückzugeben. Verwenden Sie Take<TSource>, um die ersten n Elemente zurückzugeben. Geben Sie eine absteigende Sortierreihenfolge an, um die kleinsten Elemente an den Anfang der Liste zu setzen.

Die Abfrage greift auf eine separate Methode zur Bestimmung der Dateigröße in Bytes zurück, wenn die mögliche Ausnahme eintritt, dass eine Datei in einem anderen Thread in der Zeit gelöscht wurde, in der das FileInfo-Objekt durch Aufruf von GetFiles erstellt wurde. Selbst wenn das FileInfo-Objekt bereits erstellt wurde, kann die Ausnahme auftreten, da ein FileInfo-Objekt stets versucht, seine Length-Eigenschaft zu aktualisieren, indem es beim ersten Zugriff auf die Eigenschaft die aktuellste Größe in Bytes verwendet. Durch die Platzierung des Vorgangs in einen try-catch-Block außerhalb der Abfrage folgen wir der Regel, Vorgänge, die Nebeneffekte verursachen können, in Abfragen zu vermeiden. Im Allgemeinen muss beim Behandeln von Ausnahmen größte Sorgfalt an den Tag gelegt werden, damit keine Anwendung in einem unbekannten Zustand gelassen wird.

Kompilieren des Codes

  • Erstellen Sie ein Visual Studio-Projekt für die .NET Framework-Version 3.5. Standardmäßig weist das Projekt einen Verweis auf System.Core.dll und eine using-Direktive (C#) oder eine Imports-Anweisung (Visual Basic) für den System.Linq-Namespace auf.

  • Kopieren Sie diesen Code in Ihr 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-zu-Objekte

LINQ und Dateiverzeichnisse