计算Windows文件夹大小的最快方法是什么?

我需要计算数百个文件夹的大小,有些将是10MB,有些可能是10GB,我需要一种使用C#获取每个文件夹大小的超快速方法。

我的最终结果有望成为:

Folder1 10.5GB

Folder2 230MB

Folder3 1.2GB

在.Net中没有简单的方法可以做到这一点; 你将不得不遍历每个文件和子目录。 请参阅此处的示例,了解它是如何完成的。

添加对Microsoft Scripting Runtime的引用并使用:

Scripting.FileSystemObject fso = new Scripting.FileSystemObject(); Scripting.Folder folder = fso.GetFolder([folder path]); Int64 dirSize = (Int64)folder.Size; 

如果你只需要大小,这比递归快得多。

好的,这太糟糕了,但……

使用名为dirsize.bat的递归dos批处理文件:

 @ECHO OFF IF %1x==x GOTO start IF %1x==DODIRx GOTO dodir SET CURDIR=%1 FOR /F "usebackq delims=" %%A IN (`%0 DODIR`) DO SET ANSWER=%%A %CURDIR% ECHO %ANSWER% GOTO end :start FOR /D %%D IN (*.*) DO CALL %0 "%%D" GOTO end :dodir DIR /S/-C %CURDIR% | FIND "File(s)" GOTO end :end 

注意:第5行的最后一个“%% A”后面应该有一个制表符,而不是空格。

这是您正在寻找的数据。 它会很快地完成数千个文件。 事实上,它在不到2秒的时间内完成了我的整个硬盘驱动器。

执行像dirsize | sort /R /+25这样的文件 dirsize | sort /R /+25以查看最先列出的最大目录。

祝好运。

如果您右键单击一个大目录,那么您可以看到属性需要花费大量时间来计算大小……我认为我们不能在这方面击败MS。 你可以做的一件事是索引目录/子目录的大小,如果你要一遍又一遍地计算它们……这将显着提高速度。

你可以使用这样的东西来递归地计算C#中的目录大小

 static long DirSize(DirectoryInfo directory) { long size = 0; FileInfo[] files = directory.GetFiles(); foreach (FileInfo file in files) { size += file.Length; } DirectoryInfo[] dirs = directory.GetDirectories(); foreach (DirectoryInfo dir in dirs) { size += DirSize(dir); } return size; } 

你可以做这样的事情,但是在获取文件夹大小时没有fast = true设置,你必须添加文件大小。

  private static IDictionary folderSizes; public static long GetDirectorySize(string dirName) { // use memoization to keep from doing unnecessary work if (folderSizes.ContainsKey(dirName)) { return folderSizes[dirName]; } string[] a = Directory.GetFiles(dirName, "*.*"); long b = 0; foreach (string name in a) { FileInfo info = new FileInfo(name); b += info.Length; } // recurse on all the directories in current directory foreach (string d in Directory.GetDirectories(dirName)) { b += GetDirectorySize(d); } folderSizes[dirName] = b; return b; } static void Main(string[] args) { folderSizes = new Dictionary(); GetDirectorySize(@"c:\StartingFolder"); foreach (string key in folderSizes.Keys) { Console.WriteLine("dirName = " + key + " dirSize = " + folderSizes[key]); } // now folderSizes will contain a key for each directory (starting // at c:\StartingFolder and including all subdirectories), and // the dictionary value will be the folder size } 

Dot Net Pearls有一种类似于这里描述的方法。 令人惊讶的是System.IO.DirectoryInfo类没有一个方法来执行此操作,因为它似乎是一个常见的需求,如果不对每个文件系统对象执行本机/托管转换,它可能会更快。 我认为如果速度是关键,编写一个非托管对象来进行此计算,然后从托管代码的每个目录调用一次。

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); } ///  /// Get real file size and add to total ///  /// File information 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)); } 

这个链接中有一些线索(虽然它是在Python中)来自遇到类似性能问题的人。 您可以尝试调用Win32 API以查看性能是否有所改善,但最后您将遇到同样的问题:任务只能如此快速完成,如果您必须执行很多次任务,这需要很多时间。 你能详细介绍一下你在做什么吗? 它可能会帮助人们想出一个启发式或一些秘籍来帮助你。 如果您正在进行大量计算,是否要缓存结果?

我很确定这会很慢,但我会像这样写:

 using System.IO; long GetDirSize(string dir) { return new DirectoryInfo(dir) .GetFiles("", SearchOption.AllDirectories) .Sum(p => p.Length); }