Практическое руководство. Запрос общего количества байтов в наборе папок (LINQ) (Visual Basic)

В этом примере показано, как получить общее количество байтов, используемых всеми файлами в указанной папке и всеми вложенными папками.

Пример

Метод Sum добавляет значения всех элементов, выбранных в предложении select . Этот запрос можно легко изменить, чтобы получить самый большой или наименьший файл в дереве указанных каталогов, вызвав метод Min или Max вместо Sum.

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

Если нужно подсчитать только количество байтов в указанном дереве каталогов, это можно сделать более эффективно, не создавая запрос LINQ, что приводит к затратам на создание коллекции списков в качестве источника данных. Полезность подхода LINQ увеличивается по мере того, как запрос становится более сложным или при выполнении нескольких запросов к одному источнику данных.

Запрос вызывает отдельный метод, чтобы получить длину файла. Это делается для того, чтобы обработать возможное исключение, которое будет возникать, если файл был удален в другом потоке после создания объекта в вызове FileInfoGetFiles. Несмотря на то, что FileInfo объект уже создан, исключение может произойти, так как FileInfo объект попытается обновить его Length свойство с самой текущей длиной при первом доступе к свойству. Поместив эту операцию в блок try-catch вне запроса, код следует правилу предотвращения операций в запросах, которые могут вызвать побочные эффекты. Как правило, при использовании исключений необходимо соблюдать большую осторожность, чтобы убедиться, что приложение не остается в неизвестном состоянии.

Компиляция кода

Создайте проект консольного приложения Visual Basic с инструкцией Imports для пространства имен System.Linq.

См. также