我已经阅读过关于Directory.EnumerateFiles和Directory.GetFiles()之间差异的讨论。
据我所知,他们都在内部使用 System.IO.FileSystemEnumerableFactory.CreateFileNameIterator()
区别在于EnumerateFiles可能使用延迟执行(lazy),而GetFiles()执行ToArray,因此该函数已经执行。
但是如果在迭代期间将文件和文件夹添加到字典中会发生什么。迭代是否只会迭代EnumerateFiles()中出现的项目?
更糟糕的是:如果在迭代期间删除文件会发生什么:它们是否仍会被迭代?
答案 0 :(得分:4)
感谢Michal Komorowski。然而,当我自己尝试他的解决方案时,我看到Directory.EnumerateFiles和Directory.GetFiles()之间的显着区别:
Directory.CreateDirectory(@"c:\MyTest");
// Create fies: b c e
File.CreateText(@"c:\MyTest\b.txt").Dispose();
File.CreateText(@"c:\MyTest\c.txt").Dispose();
File.CreateText(@"c:\MyTest\e.txt").Dispose();
string[] files = Directory.GetFiles(@"c:\MyTest");
var fileEnumerator = Directory.EnumerateFiles(@"c:\MyTest");
// delete file c; create file a d f
File.Delete(@"c:\MyTest\c.txt");
File.CreateText(@"c:\MyTest\a.txt").Dispose();
File.CreateText(@"c:\MyTest\d.txt").Dispose();
File.CreateText(@"c:\MyTest\f.txt").Dispose();
Console.WriteLine("Result from Directory.GetFiles");
foreach (var file in files) Console.WriteLine(file);
Console.WriteLine("Result from Directory.EnumerateFiles");
foreach (var file in fileEnumerator) Console.WriteLine(file);
这会产生不同的输出。
Result from Directory.GetFiles
c:\MyTest\b.txt
c:\MyTest\c.txt
c:\MyTest\e.txt
Result from Directory.EnumerateFiles
c:\MyTest\b.txt
c:\MyTest\d.txt
c:\MyTest\e.txt
c:\MyTest\f.txt
<强>结果:强>
因此,EnumerateFiles和GetFiles之间的使用差异不仅仅是性能。
因此,如果您希望在枚举时更改文件夹,请仔细选择所需的功能
答案 1 :(得分:0)
只有一种方法可以检查:
Directory.CreateDirectory(@"c:\\Temp");
File.Create(@"c:\\Temp\\a.txt").Close();
File.Create(@"c:\\Temp\\b.txt").Close();
File.Create(@"c:\\Temp\\c.txt").Close();
foreach (var f in Directory.EnumerateFiles(@"c:\\Temp"))
{
Console.WriteLine(f);
//Let's delete a file
File.Delete(@"c:\\Temp\\c.txt");
//Let's create a new file
File.Create(@"c:\\Temp\\d.txt").Close();
}
最初 C:\ Temp 包含3个文件:a.txt,b.txt和c.txt。在迭代期间,正在删除其中一个文件,并且正在创建一个文件。最后, C:\ Temp 包含以下文件:a.txt,b.txt和d.txt但是,在控制台中,您将看到此目录的原始内容,即:。
c:\\Temp\a.txt
c:\\Temp\b.txt
c:\\Temp\c.txt
答案 2 :(得分:0)
我做了一个不同的实验,因为我对文件枚举缓慢的情况感兴趣,而在枚举目录中创建了更多文件。例如,如果枚举循环中有一个SemaphoreSlim.WaitAsync
(用于节流目的),则可能发生缓慢枚举的情况。下面的实验首先从目标目录中删除所有文件,然后创建特定数量的初始文件,然后以100毫秒的延迟开始枚举文件,而另一个异步工作流以每150毫秒一个文件的速率创建更多文件。 。枚举器会看到新创建的文件吗?
static async Task Main(string[] args)
{
const string FOLDER_PATH = @"C:\DirectoryEnumerateFilesTest";
const int FILES_COUNT = 10;
Console.WriteLine($"Deleting files");
DeleteAllFiles(FOLDER_PATH);
Console.WriteLine($"Creating files");
await CreateFiles(FOLDER_PATH, startIndex: 1, filesCount: FILES_COUNT, delay: 0);
Console.WriteLine($"Enumerating files while creating more files");
var filePaths = Directory.EnumerateFiles(FOLDER_PATH);
var cts = new CancellationTokenSource();
var producer = CreateFiles(FOLDER_PATH,
startIndex: 501, filesCount: 100, delay: 150, cts.Token);
var enumeratedCount = 0;
foreach (var filePath in filePaths)
{
Console.WriteLine($"Enumerated: {Path.GetFileName(filePath)}");
await Task.Delay(100);
enumeratedCount++;
}
Console.WriteLine($"Total files enumerated: {enumeratedCount:#,0}");
cts.Cancel();
await producer;
}
private static void DeleteAllFiles(string folderPath)
{
int count = 0;
foreach (var filePath in Directory.GetFiles(folderPath))
{
File.Delete(filePath);
Console.WriteLine($"File deleted: {Path.GetFileName(filePath)}");
count++;
}
Console.WriteLine($"Total files deleted: {count:#,0}");
}
private static async Task CreateFiles(string folderPath,
int startIndex, int filesCount, int delay, CancellationToken token = default)
{
int count = 0;
foreach (var i in Enumerable.Range(startIndex, filesCount))
{
var delayTask = Task.Delay(delay, token);
await Task.WhenAny(delayTask);
if (delayTask.IsCanceled) break;
var fileName = $"File-{i:000}.txt";
var filePath = Path.Combine(folderPath, fileName);
File.WriteAllText(filePath, "Content");
count++;
Console.WriteLine($"File created: {fileName}");
}
Console.WriteLine($"Total files created: {count:#,0}");
}
答案是::这取决于初始文件的数量和文件名的长度。阈值大约为大约50个初始文件,但是当文件名较长时,阈值将变小。只要枚举器比文件生成器更快地运行,枚举将最终停止,在这种情况下,许多文件将保持不可见状态(通常为20个左右)。
以下是上述FILES_COUNT = 10
实验的输出(表示创建枚举器时已有10个文件)。
Deleting files
Total files deleted: 0
Creating files
File created: File-001.txt
File created: File-002.txt
File created: File-003.txt
File created: File-004.txt
File created: File-005.txt
File created: File-006.txt
File created: File-007.txt
File created: File-008.txt
File created: File-009.txt
File created: File-010.txt
Total files created: 10
Enumerating files while creating more files
Enumerated: File-001.txt
Enumerated: File-002.txt
File created: File-501.txt
Enumerated: File-003.txt
File created: File-502.txt
Enumerated: File-004.txt
Enumerated: File-005.txt
File created: File-503.txt
Enumerated: File-006.txt
File created: File-504.txt
Enumerated: File-007.txt
Enumerated: File-008.txt
File created: File-505.txt
Enumerated: File-009.txt
File created: File-506.txt
Enumerated: File-010.txt
Total files enumerated: 10
File created: File-507.txt
Total files created: 7
10个文件太少,因此枚举器没有观察到此后创建的文件。