受您的问题启发,我比较了 FileInfo 和 FileSystemObject。我测量了遍历 SSD 驱动器所需的时间。
本质上,FileInfo 比 FileSystemObject 快大约三倍。
我在我的系统上重复了测量以排除缓存效应:
test FileInfo Files: 489557 Directories: 66023
FileInfo traversal needed 12,07s
test FileSystemObject. Files: 489557 Directories: 66023
FileInfo traversal needed 38,59s
尝试使用 Windows API 可能是值得的。但是由于 Marshalling,调用和参数传递必须支付性能费用。
一个自制的 C 实用程序需要大约 8 秒来扫描 SSD。
编码:
using System;
using System.Linq;
using Scripting;
using System.Diagnostics;
using System.IO;
namespace akTest
{
class Program
{
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
testFileInfo(@"c:\");
watch.Stop();
o("FileInfo traversal needed " + (watch.ElapsedMilliseconds/1000.0).ToString("#.##") + "s");
watch.Start();
testFSO(@"c:\");
watch.Stop();
o("FileInfo traversal needed " + (watch.ElapsedMilliseconds / 1000.0).ToString("#.##") + "s");
o("");
o("Ciao!");
}
static void o(string s)
{
Console.WriteLine(s);
}
static void testFileInfo(string dir)
{
DirectoryInfo di = new DirectoryInfo(dir);
long fileCount = 0;
long dirCount = 0;
long calls = 0;
o("Testing FileInfo");
WalkDirectoryTree(di, ref fileCount, ref dirCount, ref calls);
o("testFileInfo completed. Files: " + fileCount + " Directories: " + dirCount + " Calls: " + calls);
}
static void testFSO(string dir)
{
FileSystemObject fso = new FileSystemObject();
Folder folder = fso.GetFolder(dir);
long fileCount = 0;
long dirCount = 0;
long calls = 0;
o("Testing FSO");
WalkDirectoryTree(folder, ref fileCount, ref dirCount, ref calls);
o("testFSO completed. Files: " + fileCount + " Directories: " + dirCount + " Calls: " + calls);
}
static void WalkDirectoryTree(DirectoryInfo root, ref long fileCount, ref long dirCount, ref long calls)
{
FileInfo[] files = null;
DirectoryInfo[] subDirs = null;
if (++calls % 10000 == 0)
o("" + calls);
try
{
files = root.GetFiles("*.*");
if (files != null)
{
fileCount += files.Count();
subDirs = root.GetDirectories();
dirCount += subDirs.Count();
foreach (DirectoryInfo dirInfo in subDirs)
{
WalkDirectoryTree(dirInfo, ref fileCount, ref dirCount, ref calls);
}
}
}
catch (Exception)
{
}
}
static void WalkDirectoryTree(Folder root, ref long fileCount, ref long dirCount, ref long calls)
{
Files files = null;
Folders subDirs = null;
if (++calls % 10000 == 0)
o("" + calls);
try
{
files = root.Files;
if (files != null)
{
fileCount += files.Count;
subDirs = root.SubFolders;
dirCount += subDirs.Count;
foreach (Folder fd in subDirs)
{
WalkDirectoryTree(fd, ref fileCount, ref dirCount, ref calls);
}
}
}
catch (Exception)
{
}
}
}
}