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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1118568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 08:37:51  来源:igfitidea点击:

How do I get a directory size (files in the directory) in C#?

c#asp.netwinforms.net

提问by Lloyd Powell

I want to be able to get the size of one of the local directories using C#. I'm trying to avoid the following (pseudo like code), although in the worst case scenario I will have to settle for this:

我希望能够使用 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;
    }

Basically, is there a Walk() available somewhere so that I can walk through the directory tree? Which would save the recursion of going through each sub-directory.

基本上,某处是否有可用的 Walk() 以便我可以遍历目录树?这将节省遍历每个子目录的递归。

采纳答案by Marc Gravell

If you use Directory.GetFilesyou can do a recursive seach (using SearchOption.AllDirectories), but this is a bit flaky anyway (especially if you don't have access to one of the sub-directories) - and might involve a huge single array coming back (warning klaxon...).

如果您使用,Directory.GetFiles您可以进行递归搜索(使用SearchOption.AllDirectories),但无论如何这有点不稳定(特别是如果您无权访问其中一个子目录) - 并且可能涉及一个巨大的单个数组返回(警告 klaxon ……)。

I'd be happy with the recursion approach unless I could show (via profiling) a bottleneck; and then I'd probably switch to (single-level) Directory.GetFiles, using a Queue<string>to emulate recursion.

除非我可以(通过分析)显示瓶颈,否则我会对递归方法感到满意;然后我可能会切换到 (single-level) Directory.GetFiles,使用 aQueue<string>来模拟递归。

Note that .NET 4.0 introduces some enumerator-based file/directory listing methods which save on the big arrays.

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

回答by Doliveras

I've been looking some time ago for a function like the one you ask for and from what I've found on the Internet and in MSDN forums, there is no such function.

前段时间我一直在寻找像您要求的那样的功能,并且从我在 Internet 和 MSDN 论坛上找到的内容来看,没有这样的功能。

The recursive way is the only I found to obtain the size of a Folder considering all the files and subfolders that contains.

考虑到包含的所有文件和子文件夹,递归方式是我发现的唯一一种获取文件夹大小的方法。

回答by Martin Harris

You could hide your recursion behind an extension method (to avoid the issues Marc has highlighted with the GetFiles() method):

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

public static class UserExtension
{
  public static IEnumerable<FileInfo> 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;
      }
    }
  }
}

(You probably want to add some exception handling to this for protected folders etc.)

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

Then:

然后:

using static UserExtension;

long totalSize = 0L;
var startFolder = new DirectoryInfo("<path to folder>");

// iteration
foreach(FileInfo file in startFolder.Walk())
{
    totalSize += file.Length;
}

// linq
totalSize = di.Walk().Sum(s => s.Length);

Basically the same code, but maybe a little neater...

基本上相同的代码,但也许更整洁...

回答by Tamas Czinege

Have a look at this post:

看看这个帖子:

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

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

Basically there is no clean .NET way, but there is a quite straightforward COM approach so if you're happy with using COM interop and being tied to Windows, this could work for you.

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

回答by flayn

Here my .NET 4.0 approach

这是我的 .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;
}

Or even nicer:

或者更好:

// 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();

As Gabriel pointed out this will fail if you have a restricted directory under the searchDirectory!

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

回答by Lionel KOMSA

First, forgive my poor english ;o) I had a problem that took me to this page : enumerate files of a directory and his subdirectories without blocking on an UnauthorizedAccessException, and, like the new method of .Net 4 DirectoryInfo.Enumerate..., get the first result before the end of the entire query.

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

With the help of various examples found here and there on the web, I finally write this method :

借助网络上随处可见的各种示例,我终于编写了此方法:

public static IEnumerable<FileInfo> EnumerateFiles_Recursive(this DirectoryInfo directory, string searchPattern, SearchOption searchOption, Func<DirectoryInfo, Exception, bool> handleExceptionAccess)
{
    Queue<DirectoryInfo> subDirectories = new Queue<DirectoryInfo>();
    IEnumerable<FileSystemInfo> 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();
}

I use a Queue and a recursive method to keep traditional order (content of directory and then content of first subdirectory and his own subdirectories and then content of the second...). The parameter "handleExceptionAccess" is just a function call when an exception is thrown with a directory; the function must return true to indicate that the exception must be ignored.

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

With this methode, you can write :

使用此方法,您可以编写:

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

And here we are : all exception when trying to enumerate a directory will be ignore !

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

Hope this help

希望这有帮助

Lionel

莱昂内尔

PS : for a reason I can't explain, my method is more quick than the framework 4 one...

PS:出于我无法解释的原因,我的方法比框架 4 更快...

PPS : you can get my test solutions with source for those methods : here TestDirEnumerate. I write EnumerateFiles_Recursive, EnumerateFiles_NonRecursive (use a queue to avoid recursion) and EnumerateFiles_NonRecursive_TraditionalOrder (use a stack of queue to avoid recursion and keep traditional order). Keep those 3 methods has no interest, I write them only for test the best one. I think to keep only the last one. I also wrote the equivalent for EnumerateFileSystemInfos and EnumerateDirectories.

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

回答by Kev

A very succinct way to get a folder size in .net 4.0 is below. It still suffers from the limitation of having to traverse all files recursively, but it doesn't load a potentially huge array of filenames, and it's only two lines of code.

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

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

回答by TGarrett

You should make it easy on yourself. Make a method and passthrough the location of the directory.

你应该让自己轻松一点。制作一个方法并通过目录的位置。

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

-G

-G

回答by Bernhard

the solution is already here https://stackoverflow.com/a/12665904/1498669

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

as in the duplicate How do I Get Folder Size in C#?shown -> you can do this also in c#

如重复如何在 C# 中获取文件夹大小?显示 -> 您也可以在 c# 中执行此操作

first, add the COM reference "Microsoft Scripting Runtime" to your project and use:

首先,将 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);

remember to cleanup the COM references

记得清理 COM 引用