0

我需要的是在这个函数中实现文件递归来获取子目录中的所有文件。

我想保持函数的效率(我的意思是避免在文件夹中使用大循环)

我该怎么做?

编辑:我还需要放一个布尔参数让我选择是否要启用递归。

' For Each file In Get_Files("C:\Windows", {".dll", ".ini"}) : MsgBox(file.Name) : Next

Private Function Get_Files(ByVal Path As String, ParamArray exts() As String) As List(Of IO.FileInfo)
    Return New IO.DirectoryInfo(Path).GetFiles.Where(Function(o) exts.Contains(o.Extension)).ToList
End Function

更新

我需要在 dotINSolution 修改中保留原始代码的效率,该代码返回 IO.FileInfo 列表而不是字符串列表:

Private Function Get_Files(ByVal Path As String, ByVal Recursive As Boolean, ParamArray exts() As String) As List(Of String) ' As List(Of IO.FileInfo)
    Select Case Recursive
        Case True : Return IO.Directory.GetFiles(Path, "*.*", IO.SearchOption.AllDirectories).Where(Function(o) exts.Contains(IO.Path.GetExtension(o))).ToList
        Case False : Return IO.Directory.GetFiles(Path, "*.*", IO.SearchOption.TopDirectoryOnly).Where(Function(o) exts.Contains(IO.Path.GetExtension(o))).ToList
    End Select
End Function

这是否可能没有进行重大更改或没有多次转换结果?

4

3 回答 3

4

这应该为您解决问题:)

Private Function Get_Files(ByVal Path As String, ParamArray exts() As String) As List(Of IO.FileInfo)
    Return Directory.GetFiles(Path, "*.*", SearchOption.AllDirectories).Where(Function(o) exts.Contains(Path.GetExtension(o))).ToList
End Function

编辑,可选递归:

Private Function Get_Files(ByVal Path As String, Byval searchOption As System.IO.SearchOption, ParamArray exts() As String) As List(Of IO.FileInfo)
    Return Directory.GetFiles(Path, "*.*", searchOption).Where(Function(o) exts.Contains(Path.GetExtension(o))).ToList
End Function

仅在顶级目录中搜索:

For Each file In Get_Files("C:\Windows", SearchOption.TopDirectoryOnly, {".dll", ".ini"}) : MsgBox(file.Name) : Next

进行递归搜索:

For Each file In Get_Files("C:\Windows", SearchOption.AllDirectories, {".dll", ".ini"}) : MsgBox(file.Name) : Next
于 2013-06-09T09:11:30.093 回答
4

获取 FileInfo 列表而不是文件名所需要做的就是为每个文件创建一个新的 FileInfo,如下所示:

Private Function Get_Files(ByVal rootDirectory As String, ByVal recursive As Boolean, ParamArray exts() As String) As List(Of IO.FileInfo)
    Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
    Return IO.Directory.GetFiles(rootDirectory, "*.*", searchOpt).Where(Function(o) exts.Contains(IO.Path.GetExtension(o))).Select(Function(p) New IO.FileInfo(p)).ToList
End Function

如果你Imports System.IO在代码的顶部使用,你不需要输入IO.太多,它看起来会更整洁。

编辑:

对于扩展的区分大小写测试,您可以在Enumerable.Contains方法中实现比较器:

Public Class FilenameExtensionComparer
    Implements IEqualityComparer(Of String)

    Public Function Equals1(s As String, t As String) As Boolean Implements IEqualityComparer(Of String).Equals
        Return String.Compare(s, t, StringComparison.OrdinalIgnoreCase) = 0
    End Function

    Public Function GetHashCode1(s As String) As Integer Implements IEqualityComparer(Of String).GetHashCode
        Return s.GetHashCode()
    End Function

End Class

Private Function Get_Files(ByVal rootDirectory As String, ByVal recursive As Boolean, ParamArray exts() As String) As List(Of IO.FileInfo)
    Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
    Dim filenameExtComparer As New FilenameExtensionComparer
    Return IO.Directory.GetFiles(rootDirectory, "*.*", searchOpt).Where(Function(o) exts.Contains(IO.Path.GetExtension(o), filenameExtComparer)).Select(Function(p) New IO.FileInfo(p)).ToList
End Function

我在这个问题中感觉到功能蠕变;)您应该查看所使用的 .NET 方法的文档,看看它们是否具有对您有用的重载。

编辑 2:哎呀,我看到你想要不区分大小写。我适当地调整了比较器。

于 2013-06-10T17:48:57.877 回答
0

最后,由于@Andrew Morton 和@dotINSolution 的修改,这是我的通用函数,带有两个额外的重载来改进函数的使用:

#Region " Get Files "

    ' [ Get Files Function ]
    '
    ' Examples :
    '
    ' For Each file In Get_Files("C:\Windows", False) : MsgBox(file.Name) : Next
    '
    ' For Each file In Get_Files("C:\Windows", True, "dll")   : MsgBox(file.Name) : Next
    ' For Each file In Get_Files("C:\Windows", True, ".dll")  : MsgBox(file.Name) : Next
    ' For Each file In Get_Files("C:\Windows", True, "*.dll") : MsgBox(file.Name) : Next
    '
    ' For Each file In Get_Files("C:\Windows", False, {"dll", "ini"})     : MsgBox(file.Name) : Next
    ' For Each file In Get_Files("C:\Windows", False, {".dll", ".ini"})   : MsgBox(file.Name) : Next
    ' For Each file In Get_Files("C:\Windows", False, {"*.dll", "*.ini"}) : MsgBox(file.Name) : Next

    ' Get Files {directory} {recursive}
    Private Function Get_Files(ByVal directory As String, ByVal recursive As Boolean) As List(Of IO.FileInfo)
        Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
        Return IO.Directory.GetFiles(directory, "*", searchOpt).Select(Function(p) New IO.FileInfo(p)).ToList
    End Function

    ' Get Files {directory} {recursive} {ext}
    Private Function Get_Files(ByVal directory As String, ByVal recursive As Boolean, ext As String) As List(Of IO.FileInfo)

        If ext.StartsWith("*") Then
            ext = ext.Substring(1, ext.Length - 1)
        ElseIf Not ext = "*" AndAlso Not ext.StartsWith(".") Then
            ext = ("." & ext)
        ElseIf ext = "*" Then
            ext = Nothing
        End If

        Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
        Return IO.Directory.GetFiles(directory, "*" & ext, searchOpt).Select(Function(p) New IO.FileInfo(p)).ToList

    End Function

    ' Get Files {directory} {recursive} {exts()}
    Private Function Get_Files(ByVal directory As String, ByVal recursive As Boolean, ParamArray exts() As String) As List(Of IO.FileInfo)

        Dim FileExtensions(exts.Count) As String

        Dim ExtCount As Int64 = 0

        For Each ext In exts
            If ext.StartsWith("*") Then
                FileExtensions(ExtCount) = ext.Substring(1, ext.Length - 1)
            ElseIf Not ext = "*" AndAlso Not ext.StartsWith(".") Then
                FileExtensions(ExtCount) = ("." & ext)
            ElseIf Not ext = "*" AndAlso ext.StartsWith(".") Then
                FileExtensions(ExtCount) = ext
            ElseIf ext = "*" Then
                FileExtensions(ExtCount) = Nothing
            End If
            ExtCount += 1
        Next

        Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
        Dim filenameExtComparer As New FilenameExtensionComparer
        Return IO.Directory.GetFiles(directory, "*.*", searchOpt).Where(Function(o) FileExtensions.Contains(IO.Path.GetExtension(o), filenameExtComparer)).Select(Function(p) New IO.FileInfo(p)).ToList

    End Function

    ' FilenameExtensionComparer
    Public Class FilenameExtensionComparer : Implements IEqualityComparer(Of String)

        Public Function Equals1(s As String, t As String) As Boolean Implements IEqualityComparer(Of String).Equals
            Return String.Compare(s, t, StringComparison.OrdinalIgnoreCase) = 0
        End Function

        Public Function GetHashCode1(s As String) As Integer Implements IEqualityComparer(Of String).GetHashCode
            Return s.GetHashCode()
        End Function

    End Class

#End Region
于 2013-06-11T09:41:39.957 回答