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

时间:2017-05-22 12:13:06

标签: vb.net io directory getfiles

我有一个文件夹浏览器对话框,填充了system.io.directory.getfiles的目录位置(路径)。问题是,如果你不小心选择了一个带有数量或数千个文件的文件夹(这个应用程序根本不需要这个文件),它会在抓取所有文件时锁定应用程序。我所抓取的只是作为字符串的目录位置,并希望限制可以获取的文件数量。这是我当前的代码无效。

 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

1 个答案:

答案 0 :(得分:1)

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

  

EnumerateFiles和GetFiles方法的不同之处如下:使用EnumerateFiles时,可以在返回整个集合之前开始枚举名称集合;当您使用GetFiles时,您必须等待返回整个名称数组,然后才能访问该数组。因此,当您使用许多文件和目录时,EnumerateFiles可以更有效。

所以,例如,你可以这样做:

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

Take是一个LINQ扩展方法,它只返回任何IEnumerable(Of T)列表中的前x个项目。因此,为了使该行有效,您需要导入System.Linq命名空间。如果您不能或不想使用LINQ,您可以实现自己的方法来执行相同的操作(在for循环中迭代IEnumerable列表并在仅读取第一个后返回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
    ' ...