如何加快构建网络目录中所有文件列表的代码?



我有一个WPF程序,它可以获取某个网络目录中的所有目录,并在listview中列出它们。

问题是目录太多了,加载列表可能需要5秒。

我想知道是否有一种方法可以用更有效的代码来加速这一点。或者甚至是一种将列表存储在数组中的方法,并且在第一次之后每次都查找更改?

For Each i As String In Directory.GetDirectories(dir)
    If File.Exists(Path.GetFullPath(i) & "cover.jpg") Then
        If (File.GetAttributes(Path.GetFullPath(i)) And FileAttributes.Hidden) <> FileAttributes.Hidden Then
            Dim foldername As String = Path.GetFileName(i)
            Dim moviename As String = foldername
            If moviename.Length > 4 Then
                If moviename.Substring(0, 4) = "The " Then
                    moviename = moviename.Remove(0, 4)
                End If
            End If
            Dim display As Boolean = True
            If IO.Directory.GetDirectories(Path.GetFullPath(i)).Length < 1 Then
                If IO.Directory.GetFiles(Path.GetFullPath(i), "*.avi").Length < 1 Then
                    If IO.Directory.GetFiles(Path.GetFullPath(i), "*.mp4").Length < 1 Then
                        If IO.Directory.GetFiles(Path.GetFullPath(i), "*.mkv").Length < 1 Then
                            display = False
                        End If
                    End If
                End If
            End If
            If display = True Then
                Showslist.Items.Add(New With {Key .img = Path.GetFullPath(i) & "cover.jpg", .name = foldername, .path = Path.GetFullPath(i), .created = Directory.GetCreationTime(Path.GetFullPath(i)), .moviename = moviename})
            End If
        End If
    End If
Next

1。不要多次读取目录的内容。相反,一次读取所有需要的内容并将其缓存到一个(内存中的)变量中。这将有助于提高性能,因为访问内存比执行I/O要快得多(这里是访问文件系统)。例如:

If IO.Directory.GetFiles(…, "*.avi").Length < 1 Then
    If IO.Directory.GetFiles(…, "*.mp4").Length < 1 Then
        If IO.Directory.GetFiles(…, "*.mkv").Length < 1 Then
            …

您刚刚查询了同一目录三次。您可以将其更改为只读取一次内容(因此可能会将代码速度提高三次),然后在内存中对其进行过滤:

'Imports System.IO
'Imports System.Linq
' access the file system only once and store the results in-memory…
Dim filePaths As String() = Directory.GetFiles(…, "*")
' … and perform everything else on that in-memory cache:
If Not filePaths.Any(Function(fp) Path.GetExtension(fp) = ".avi") Then
    If Not filePaths.Any(…) Then
        If Not filePaths.Any(…) Then
            …

<子>注::也许值得指出的是,与Directory.GetFiles不同,System.IO.Path方法不应该导致昂贵的文件系统命中:它们只是对已知包含文件系统路径的字符串进行操作。


2。考虑递归地读取根目录的完整内容。 Directory.GetFiles方法有一个过载的Directory.GetFiles(String, String, SearchOption), SearchOption参数可以设置为SearchOption.AllDirectories。在这种情况下,您不仅可以从指定的目录本身获取内容,还可以从它的所有子目录获取内容。

这意味着,您将需要对Directory.GetFiles(对于根目录)进行单个调用,而不是多次调用,这意味着您将再次减少昂贵的I/O调用的数量。将结果存储在一个数组中,然后从那里开始构建WPF列表。

' read the contents of the network root directory, including all of its sub-directories…
Dim filePaths As String() = Directory.GetFiles(…, "*", SearchOption.AllDirectories)
' …and do everything else using the in-memory cache built above:
For Each filePath As String in filePaths
    …
    Showslist.Items.Add(…)
Next

最新更新