如何使用Directory.EnumerateFiles

时间:2015-07-30 03:27:19

标签: vb.net

msdn(https://msdn.microsoft.com/en-us/library/dd383458(v=vs.110).aspx)说:

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

如何在返回整个集合之前开始使用该集合?

以下代码为大约45000个文件的目录提供了超过3分钟的经过时间

Dim TIme1, TIme2 As String
TIme1 = TimeString
Dim DirFiles As Generic.List(Of String) = New Generic.List(Of String)(Directory.EnumerateFiles(SourceDirectory))
Dim NumberOfFiles As Integer
NumberOfFiles = DirFiles.Count()
TIme2 = TimeString
MsgBox("Begin time " & TIme1 & "There are " & NumberOfFiles & " Photos in the Directory ." & SourceDirectory & "End Time " & TIme2)

在完全阅读完集合之前,我是否可以在Dirfiles中使用条目?怎么样?

在Microsoft推出Windows之前,我曾经是一名专业程序员。我对Windows编程的经验很少。

5 个答案:

答案 0 :(得分:2)

虽然您无法充分利用EnumerateFiles返回的文件数量,但您可以开始使用集合中的单个文件而不会出现For Each循环等任何不需要的延迟其工作要素的数量。

例如,您可以这样做:

Dim FileCount As Integer
Dim files = Directory.EnumerateFiles(srcDir)
For Each file in files
    'Do something with this file
    ' e.g.
    TextBox1.AppendText(file & vbCrLf)
    FileCount += 1
Next
MsgBox ( FileCount.ToString & " files processed.")

所以你看看它是如何使用的?

[NB:手绘类型代码..可能包含拼写错误。它只是为了解释这个概念。]

答案 1 :(得分:1)

EnumerateFiles允许您在找到所有文件之前启动处理文件。您似乎想知道文件的数量。在找到所有文件之前,您无法知道,因此EnumerateFiles在这种情况下无法为您提供帮助。

答案 2 :(得分:1)

GetFiles的签名是Directory.GetFiles(path As String) As String()。为了返回结果,它必须先击中硬盘驱动器并构建整个阵列。如果有45,000个文件,那么它必须构建一个包含45,000个元素的数组才能给你一个结果。

EnumerateFiles的签名是Directory.EnumerateFiles(path As String) As IEnumerable(Of String)。在这种情况下,它根本不需要点击硬盘驱动器就能给你一个响应。因此,无论文件数量多少,您都应该能够立即获得结果。

拿这个测试代码:

Dim sw = Stopwatch.StartNew()
Dim files = Directory.GetFiles("C:\Windows\System32")
sw.Stop()
Console.WriteLine(sw.Elapsed.TotalMilliseconds)

我得到大约6.5毫秒的结果来返回文件。

但如果我将GetFiles更改为EnumerateFiles,我会在0.07毫秒内得到一个结果。为此文件夹调用GetFiles要慢近100倍!

这是因为EnumerateFiles返回IEnumerable<string>IEnumerable(Of T)的界面是:

Public Interface IEnumerable(Of Out T)
    Inherits IEnumerable
    Function GetEnumerator() As IEnumerator(Of T)
End Interface

每当我们打电话给foreach.Count().ToArray()时,我们就会调用GetEnumerator(),而IEnumerator(Of T)会返回Public Interface IEnumerator(Of Out T) Inherits IDisposable Inherits IEnumerator ReadOnly Property Current As T Function MoveNext() As Boolean Sub Reset() End Interface 类型的另一个对象有这个签名:

MoveNext

这个枚举器实际上做了返回所有文件的艰苦工作。第一次调用Current后,第一个文件名立即在MoveNext中可用。然后在循环中调用false,直到它返回Current然后您知道循环结束。同时,您可以从EnumerateFiles属性中收集所有文件。

因此,在您的代码中,如果您对返回的每个文件执行某些操作,那么New Generic.List(Of String)(Directory.EnumerateFiles(SourceDirectory))将成为可行的方法。

但是因为你正在做EnumerateFiles,所以你立刻强迫整个可枚举的迭代。使用import json from json import JSONEncoder class A: def __init__ (self, n, a): self.n = n self.a = a class B: def __init__ (self, b, listOfA): self.b = b self.listOfA = [] for a in listOfA: self.listOfA.append(a) class AEncoder(JSONEncoder): def default (self, obj): if isinstance (obj, A): return { 'n' : obj.n, 'a' : obj.a } return json.JSONEncoder.default(self, obj) class BEncoder(JSONEncoder): def default (self, obj): if isinstance (obj, B): a = AEncoder() return { 'b' : obj.b, 'listOfA' : [a.default(x) for x in obj.listOfA] } return json.JSONEncoder.default(self, obj) listOfA = [A('n1', 'a1'), A('n2', 'a2')] tmpB = B('b', listOfA) print(json.dumps(tmpB, cls=BEncoder)) 的任何优势都会立即丢失。

答案 3 :(得分:0)

GetFiles方法将实现目录中的整个文件列表。现在调用的首选方法是Directory.EnumerateFiles,因为它会将文件流回(通过类似于类似的机制),因为对OS的底层调用会产生结果。

使用GetFiles / GetDirectories的解决方案有点慢,因为需要创建对象。另一方面,使用枚举不会这样做,它不会创建任何临时对象。

无论哪种方式最终还是迭代发生......

示例文件计数...

 Directory.EnumerateFiles(directory, filetype, SearchOption.AllDirectories).Count()

答案 4 :(得分:0)

我现在在enumeratefiles启动之前使用以下内容

Public Function FileCount(PathName As String) As Long
    Dim fso As Scripting.FileSystemObject
    Dim fld As Scripting.Folder
    fso = CreateObject("Scripting.FileSystemObject")
    If fso.FolderExists(PathName) Then
        fld = fso.GetFolder(PathName)
        FileCount = fld.Files.Count
    End If
End Function

这需要Microsoft Scripting Runtime(在项目中设置对VB脚本运行时库的引用)