限制从 system.io.directory.getfiles 抓取的文件数量

Limiting the amount of files grabbed from system.io.directory.getfiles

我有一个文件夹浏览器对话框,其中填充了 system.io.directory.getfiles 的目录位置(路径)。问题是,如果您不小心 select 一个包含数百个或数千个文件的文件夹(您没有理由为此应用程序需要它),它会在抓取所有文件时锁定该应用程序。我所抓取的只是作为字符串的目录位置,并想限制可以抓取的文件数量。这是我当前无法使用的代码。

 If JigFolderBrowse.ShowDialog = DialogResult.OK Then
            Dim dirs(50) As String
            dirs = System.IO.Directory.GetFiles(JigFolderBrowse.SelectedPath.ToString, "*", System.IO.SearchOption.AllDirectories)
            If dirs.Length> 50 Then
                MsgBox("Too Many Files Selected" + vbNewLine + "Select A Smaller Folder To Be Organized")
                Exit Sub
            End If
            'Seperate Each File By Type
            For i = 0 To dirs.Length - 1
                    If Not dirs(i).Contains("~$") Then
                        If dirs(i).Contains(".SLDPRT") Or dirs(i).Contains(".sldprt") Then
                            PartsListBx.Items.Add(dirs(i))
                        ElseIf dirs(i).Contains(".SLDASM") Or dirs(i).Contains(".sldasm") Then
                            AssemListBx.Items.Add(dirs(i))
                        ElseIf dirs(i).Contains(".SLDDRW") Or dirs(i).Contains(".slddrw") Then
                            DrawingListBx.Items.Add(dirs(i))
                        ElseIf dirs(i).Contains(".pdf") Or dirs(i).Contains(".PDF") Then
                            PDFsListBx.Items.Add(dirs(i))
                        ElseIf dirs(i).Contains(".DXF") Or dirs(i).Contains(".dxf") Then
                            DXFsListBx.Items.Add(dirs(i))
                        ElseIf Not dirs(i).Contains(".db") Then
                            OtherFilesListBx.Items.Add(dirs(i))
                        End If
                    End If

Directory.GetFiles 方法总是在返回之前检索匹配文件的完整列表。没有办法限制它(除了指定更窄的搜索模式之外)。但是,Directory.EnumerateFiles 方法可以满足您的需要。来自 MSDN article:

The EnumerateFiles and GetFiles methods differ as follows: When you use EnumerateFiles, you can start enumerating the collection of names before the whole collection is returned; when you use GetFiles, you must wait for the whole array of names to be returned before you can access the array. Therefore, when you are working with many files and directories, EnumerateFiles can be more efficient.

因此,例如,您可以这样做:

dirs = Directory.
    EnumerateFiles(
        JigFolderBrowse.SelectedPath.ToString(), 
        "*", 
        SearchOption.AllDirectories).
    Take(50).
    ToArray()

Take 是一种 LINQ 扩展方法,它 returns 仅是任何 IEnumerable(Of T) 列表中的第一个 x 项。因此,为了使该行工作,您需要导入 System.Linq 命名空间。如果你不能或不想使用 LINQ,你可以只实现你自己的方法来做同样的事情(在 for 循环中迭代 IEnumerable 列表,然后 returns仅阅读前 50 项)。

旁注 1:未使用的数组

此外,值得一提的是,在您的代码中,您将 dirs 变量初始化为指向一个包含 50 个元素的字符串数组。然后,在下一行中,将其设置为指向一个全新的数组(由 Directory.GetFiles 方法返回的数组)。虽然它没有破坏功能,但它不必要地低效。你正在创建那个额外的数组,只是无缘无故地给垃圾收集器额外的工作。您永远不会使用第一个数组。它只是在下一行中被取消引用和丢弃。最好将数组变量创建为 null:

Dim dirs() As String

Dim dirs() As String = Nothing

或者,更好的是:

Dim dirs() As String = Directory.
    EnumerateFiles(
        JigFolderBrowse.SelectedPath.ToString(), 
        "*", 
        SearchOption.AllDirectories).
    Take(50).
    ToArray()

附注 2:文件扩展名比较

此外,您似乎正在尝试以不区分大小写的方式比较文件扩展名。你这样做的方式有两个问题。首先,您只将它与两个值进行比较:全小写(例如“.pdf”)和全大写(例如“.PDF”)。这不适用于大小写混合(例如“.Pdf”)。

无可否认,String.Contains 方法没有区分大小写的选项。因此,虽然有点矫揉造作,但最好的选择是使用 String.IndexOf 方法,它确实有一个不区分大小写的选项:

If dirs(i).IndexOf(".pdf", StringComparison.CurrentCultureIgnoreCase) <> -1 Then

然而,第二个问题使我的最后一点建议无效,即您正在检查字符串是否包含特定的文件扩展名,而不是检查它是否 它。因此,例如,像 "My.pdf.zip" 这样的文件名仍然匹配,即使它的扩展名是“.zip”而不是“.pdf”。也许这是您的意图,但如果不是,我建议使用 Path.GetExtension 方法获取文件名的实际扩展名,然后进行比较。例如:

Dim ext As String = Path.GetExtension(dirs(i))
If ext.Equals("pdf", StringComparison.CurrentCultureIgnoreCase) Then
    ' ...