我能找到的 4.0-4.5 框架上计算文件大小及其在磁盘上的数量的最快方法是:
using System.IO;
using System.Threading;
using System.Threading.Tasks;
class FileCounter
{
private readonly int _clusterSize;
private long _filesCount;
private long _size;
private long _diskSize;
public void Count(string rootPath)
{
// Enumerate files (without real execution of course)
var filesEnumerated = new DirectoryInfo(rootPath)
.EnumerateFiles("*", SearchOption.AllDirectories);
// Do in parallel
Parallel.ForEach(filesEnumerated, GetFileSize);
}
/// <summary>
/// Get real file size and add to total
/// </summary>
/// <param name="fileInfo">File information</param>
private void GetFileSize(FileInfo fileInfo)
{
Interlocked.Increment(ref _filesCount);
Interlocked.Add(ref _size, fileInfo.Length);
}
}
var fcount = new FileCounter("F:\\temp");
fcount.Count();
这种方法对我来说似乎是我在 .net 平台上能找到的最好的方法。顺便说一句,如果您需要计算磁盘上的集群大小和实际大小,您可以执行以下操作:
using System.Runtime.InteropServices;
private long WrapToClusterSize(long originalSize)
{
return ((originalSize + _clusterSize - 1) / _clusterSize) * _clusterSize;
}
private static int GetClusterSize(string rootPath)
{
int sectorsPerCluster = 0, bytesPerSector = 0, numFreeClusters = 0, totalNumClusters = 0;
if (!GetDiskFreeSpace(rootPath, ref sectorsPerCluster, ref bytesPerSector, ref numFreeClusters,
ref totalNumClusters))
{
// Satisfies rule CallGetLastErrorImmediatelyAfterPInvoke.
// see http://msdn.microsoft.com/en-us/library/ms182199(v=vs.80).aspx
var lastError = Marshal.GetLastWin32Error();
throw new Exception(string.Format("Error code {0}", lastError));
}
return sectorsPerCluster * bytesPerSector;
}
[DllImport(Kernel32DllImport, SetLastError = true)]
private static extern bool GetDiskFreeSpace(
string rootPath,
ref int sectorsPerCluster,
ref int bytesPerSector,
ref int numFreeClusters,
ref int totalNumClusters);
当然你需要在第一个代码部分重写 GetFileSize():
private long _diskSize;
private void GetFileSize(FileInfo fileInfo)
{
Interlocked.Increment(ref _filesCount);
Interlocked.Add(ref _size, fileInfo.Length);
Interlocked.Add(ref _diskSize, WrapToClusterSize(fileInfo.Length));
}