如何:查询目录树中的一个或多个最大的文件 (LINQ) (Visual Basic)

此示例显示了与文件大小相关的五个查询(以字节为单位):

  • 如何检索最大文件的大小(以字节为单位)。

  • 如何检索最小文件的大小(以字节为单位)。

  • 如何从指定根文件夹下的一个或多个文件夹中检索 FileInfo 对象最大或最小文件。

  • 如何检索序列,例如 10 个最大文件。

  • 如何根据文件的大小(以字节为单位)将文件排序到组中,忽略小于指定大小的文件。

示例:

下面的示例包含五个单独的查询,这些查询显示如何查询和分组文件,具体取决于其文件大小(以字节为单位)。 可以轻松修改这些示例,以便将查询基于 FileInfo 对象的其他一些属性。

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  

若要返回一个或多个完整的 FileInfo 对象,查询首先必须检查数据源中的每个对象,然后按其 Length 属性的值对其进行排序。 然后,它可以返回具有最大长度的单个序列或序列。 用于 First 返回列表中的第一个元素。 使用 Take 返回前 n 个元素。 指定降序排序顺序,将最小的元素放在列表的开头。

查询调用单独的方法来获取文件大小(以字节为单位),以便处理可能引发的异常情况,这种情况发生在自从调用FileInfo中创建GetFiles对象以来,文件在其他线程上被删除的时间段内。 即使 FileInfo 对象已经创建,仍可能发生异常,因为 FileInfo 对象在首次访问该属性时,将尝试使用最新的字节大小刷新其 Length 属性。 通过将此操作置于查询外部的 try-catch 块中,我们遵循了一条避免在查询中执行可能导致副作用的操作的规则。 一般情况下,在使用异常时必须格外谨慎,以确保应用程序不会处于未知状态。

编译代码

创建 Visual Basic 控制台应用程序项目,其中包含 Imports System.Linq 命名空间的语句。

另请参阅