如何在C#中获取目录大小(目录中的文件)?

我希望能够使用C#获取其中一个本地目录的大小。 我试图避免以下(伪代码),虽然在最坏的情况下我将不得不解决这个问题:

int GetSize(Directory) { int Size = 0; foreach ( File in Directory ) { FileInfo fInfo of File; Size += fInfo.Size; } foreach ( SubDirectory in Directory ) { Size += GetSize(SubDirectory); } return Size; } 

基本上,在某处可以使用Walk(),以便我可以浏览目录树吗? 这将保存通过每个子目录的递归。

如果您使用Directory.GetFiles您可以执行递归搜索(使用SearchOption.AllDirectories ),但这有点SearchOption.AllDirectories (特别是如果您无法访问其中一个子目录) – 并且可能涉及一个巨大的单个目录arrays回来(警告klaxon ……)。

我会对递归方法感到满意,除非我能显示(通过分析)瓶颈; 然后我可能会切换到(单级) Directory.GetFiles ,使用Queue来模拟递归。

请注意,.NET 4.0引入了一些基于枚举器的文件/目录列表方法,这些方法可以节省大数组。

在.net 4.0中获取文件夹大小的一种非常简洁的方法如下。 它仍然受到必须递归遍历所有文件的限制,但它不会加载潜在的大量文件名,而且只有两行代码。

 private static long GetDirectorySize(string folderPath) { DirectoryInfo di = new DirectoryInfo(folderPath); return di.EnumerateFiles("*.*", SearchOption.AllDirectories).Sum(fi => fi.Length); } 

这是我的.NET 4.0方法

 public static long GetFileSizeSumFromDirectory(string searchDirectory) { var files = Directory.EnumerateFiles(searchDirectory); // get the sizeof all files in the current directory var currentSize = (from file in files let fileInfo = new FileInfo(file) select fileInfo.Length).Sum(); var directories = Directory.EnumerateDirectories(searchDirectory); // get the size of all files in all subdirectories var subDirSize = (from directory in directories select GetFileSizeSumFromDirectory(directory)).Sum(); return currentSize + subDirSize; } 

甚至更好:

 // get IEnumerable from all files in the current dir and all sub dirs var files = Directory.EnumerateFiles(searchDirectory,"*",SearchOption.AllDirectories); // get the size of all files long sum = (from file in files let fileInfo = new FileInfo(file) select fileInfo .Length).Sum(); 

正如Gabriel所指出的,如果您在searchDirectory下有一个受限制的目录,这将失败!

您可以隐藏扩展方法后面的递归(以避免Marc使用GetFiles()方法突出显示的问题):

 public static IEnumerable Walk(this DirectoryInfo directory) { foreach(FileInfo file in directory.GetFiles()) { yield return file; } foreach(DirectoryInfo subDirectory in directory.GetDirectories() { foreach(FileInfo file in subDirectory.Walk()) { yield return file; } } } 

(您可能希望为受保护的文件夹等添加一些exception处理)

然后:

 int totalSize = 0; foreach(FileInfo file in directory.Walk()) { totalSize += file.Length; } 

基本上相同的代码,但也许有点整洁……

首先,请原谅我糟糕的英语; o)我遇到了一个问题,带我进入这个页面:枚举目录及其子目录的文件而不会阻止UnauthorizedAccessException,并且像.Net 4 DirectoryInfo.Enumerate的新方法一样…… ,在整个查询结束之前获取第一个结果。

借助在网上找到的各种示例的帮助,我终于编写了这个方法:

 public static IEnumerable EnumerateFiles_Recursive(this DirectoryInfo directory, string searchPattern, SearchOption searchOption, Func handleExceptionAccess) { Queue subDirectories = new Queue(); IEnumerable entries = null; // Try to get an enumerator on fileSystemInfos of directory try { entries = directory.EnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly); } catch (Exception e) { // If there's a callback delegate and this delegate return true, we don't throw the exception if (handleExceptionAccess == null || !handleExceptionAccess(directory, e)) throw; // If the exception wasn't throw, we make entries reference an empty collection entries = EmptyFileSystemInfos; } // Yield return file entries of the directory and enqueue the subdirectories foreach (FileSystemInfo entrie in entries) { if (entrie is FileInfo) yield return (FileInfo)entrie; else if (entrie is DirectoryInfo) subDirectories.Enqueue((DirectoryInfo)entrie); } // If recursive search, we make recursive call on the method to yield return entries of the subdirectories. if (searchOption == SearchOption.AllDirectories) { DirectoryInfo subDir = null; while (subDirectories.Count > 0) { subDir = subDirectories.Dequeue(); foreach (FileInfo file in subDir.EnumerateFiles_Recursive(searchPattern, searchOption, handleExceptionAccess)) { yield return file; } } } else subDirectories.Clear(); } 

我使用一个Queue和一个递归方法来保持传统的顺序(目录的内容,然后是第一个子目录和他自己的子目录的内容,然后是第二个的内容……)。 参数“handleExceptionAccess”只是在用目录抛出exception时的函数调用; 该函数必须返回true以指示必须忽略该exception。

使用这种方法,你可以写:

 DirectoryInfo dir = new DirectoryInfo("c:\\temp"); long size = dir.EnumerateFiles_Recursive("*", SearchOption.AllDirectories, (d, ex) => true).Sum(f => f.Length); 

我们在这里:尝试枚举目录时的所有exception都将被忽略!

希望这有帮助

莱昂内尔

PS:由于一个我无法解释的原因,我的方法比框架4更快…

PPS:您可以使用这些方法的源代码获取我的测试解决方案:此处为TestDirEnumerate 。 我编写EnumerateFiles_Recursive,EnumerateFiles_NonRecursive(使用队列来避免递归)和EnumerateFiles_NonRecursive_TraditionalOrder(使用一堆队列来避免递归并保持传统顺序)。 保持这3种方法没有兴趣,我写它们只是为了测试最好的方法。 我认为只保留最后一个。 我还写了EnumerateFileSystemInfos和EnumerateDirectories的等价物。

看看这篇文章:

http://social.msdn.microsoft.com/forums/en-US/vbgeneral/thread/eed54ebe-facd-4305-b64b-9dbdc65df04e

基本上没有干净的.NET方法,但有一个非常简单的COM方法,所以如果你对使用COM互操作并与Windows绑定感到满意,这可能对你有用。

解决方案已经在这里https://stackoverflow.com/a/12665904/1498669

如在副本中如何在C#中获取文件夹大小? 显示 – >你也可以在c#中做到这一点

首先,将COM参考“Microsoft Scripting Runtime”添加到您的项目并使用:

 var fso = new Scripting.FileSystemObject(); var folder = fso.GetFolder(@"C:\Windows"); double sizeInBytes = folder.Size; // cleanup COM System.Runtime.InteropServices.Marshal.ReleaseComObject(folder); System.Runtime.InteropServices.Marshal.ReleaseComObject(fso); 

记得清理COM引用

我前段时间一直在寻找一个像你要求的function,以及我在互联网和MSDN论坛上发现的function,没有这样的function。

考虑到包含的所有文件和子文件夹,我只能找到获取文件夹大小的递归方式。

你应该让自己轻松自如。 创建一个方法并直接通过目录的位置。

  private static long GetDirectorySize(string location) { return new DirectoryInfo(location).GetFiles("*.*", SearchOption.AllDirectories).Sum(file => file.Length); } 

-G