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

时间:2014-08-07 06:19:36

标签: vb.net .net system.io.directory

我有一个WPF程序,它抓取某个网络目录中的所有目录,并在列表视图中列出它们。

问题是目录太多,列表加载最多可能需要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 个答案:

答案 0 :(得分:2)

<强> 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
            …
  

PS:也许值得指出的是,与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