Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中获得目录大小(目录中的文件)?_C#_Asp.net_Winforms_.net - Fatal编程技术网

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

如何在C#中获得目录大小(目录中的文件)?,c#,asp.net,winforms,.net,C#,Asp.net,Winforms,.net,我希望能够使用C#获得一个本地目录的大小。我试图避免以下情况(伪代码),尽管在最坏的情况下,我必须满足于此: int GetSize(Directory) { int Size = 0; foreach ( File in Directory ) { FileInfo fInfo of File; Size += fInfo.Size; } fore

我希望能够使用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()可以让我遍历目录树?这将节省遍历每个子目录的递归。

我不久前一直在寻找一个类似您要求的函数,从我在Internet和MSDN论坛上找到的内容来看,没有这样的函数

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

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

如果使用
目录。GetFiles
可以进行递归搜索(使用
SearchOption.AllDirectories
),但这还是有点古怪(特别是如果您没有访问其中一个子目录的权限)-并且可能需要一个巨大的数组返回(警告klaxon…)

我很乐意使用递归方法,除非我可以(通过分析)显示瓶颈;然后我可能会切换到(单级)
Directory.GetFiles
,使用
队列来模拟递归


请注意,.NET 4.0引入了一些基于枚举数的文件/目录列表方法,这些方法保存在大数组中。

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

公共静态类UserExtension
{
公共静态IEnumerable Walk(此DirectoryInfo目录)
{
foreach(目录.GetFiles()中的FileInfo文件)
{
生成返回文件;
}
foreach(directory.GetDirectories()中的DirectoryInfo子目录)
{ 
foreach(子目录.Walk()中的FileInfo文件)
{
生成返回文件;
}
}
}
}
(对于受保护的文件夹等,您可能希望为此添加一些异常处理。)

然后:

使用静态用户扩展;
长总尺寸=0升;
var startFolder=新目录信息(“”);
//迭代
foreach(startFolder.Walk()中的FileInfo文件)
{
totalSize+=文件长度;
}
//林克
totalSize=di.Walk().Sum(s=>s.Length);

基本上相同的代码,但可能有点整洁…

看看这篇文章:


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

这里是我的.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下有一个受限目录,则此操作将失败!

首先,请原谅我的蹩脚英语;o) 我遇到了一个问题,这个问题把我带到了这个页面:枚举目录及其子目录的文件,而不阻塞未经授权的访问异常,并且,像.Net 4 DirectoryInfo.enumerate…的新方法一样,在整个查询结束之前获得第一个结果

借助于web上随处可见的各种示例,我最终编写了以下方法:

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();
}
现在我们看到了:当尝试枚举目录时,所有异常都将被忽略

希望这有帮助

莱昂内尔

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

PPS:您可以从这些方法的源代码中获得我的测试解决方案:这里。我编写EnumerateFiles\u Recursive、EnumerateFiles\u NonRecursive(使用队列避免递归)和EnumerateFiles\u NonRecursive\u TraditionalOrder(使用队列堆栈避免递归并保持传统顺序)。保持这3种方法没有兴趣,我写它们只是为了测试最好的方法。我想只保留最后一个。
我还为EnumerateFileSystemFos和EnumerateDirectory编写了等效程序。

下面是在.NET4.0中获取文件夹大小的一种非常简洁的方法。它仍然受到必须递归遍历所有文件的限制,但它不会加载潜在的巨大文件名数组,而且只需两行代码。确保使用名称空间
System.IO
System.Linq

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

你应该放松自己。创建一个方法并遍历目录的位置

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

-解决方案已经在这里了

如图所示->您也可以在c中执行此操作#

首先,将COM引用“Microsoft脚本运行时”添加到项目中,并使用:

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引用

最后一行代码中的小错误,应该是://get the size of all files long sum=(从files in files let fileInfo=new fileInfo(file)选择fileInfo.Length).sum();如果您在searchDirectory下有一个受限目录,它将失败!在未来版本的框架中看到这一解决方案:感谢您的评论Gabriel。我已经修复了输入错误,并包含了可能的失败警告。我在这个版本中犯了一个错误,因为我使用searchPattern搜索目录。因此,如果一个子目录与searchPattern不匹配,我不会对其进行探索…[br]我编写了新版本以更正此问题:但是,我必须对目录执行两个请求:一个使用searchPattern,另一个不使用searchPattern==>性能不如以前。因此,我添加了一个不使用searchPattern的版本,速度更快。看看我的测试解决方案:也许我遗漏了一些东西,但是使用这种方法,您仍然会得到不完整的列表,对吗?如果我被授权查看文件夹A和C而不是B,并且
Enumerate
检查A,然后检查B,然后检查C,它将停止使用B,并且无法计算C。我建议您使用*而不是*因为文件名不需要。我理解你的推理,但我认为这是不必要的,因为Windows操作系统将匹配**针对文件/文件夹名称的模式,无论它们是否包含“.”。我认为这没什么区别,但我很想知道我是否错了。当然,如果是Mono在不同的平台上运行
    private static long GetDirectorySize(string location) {
        return new DirectoryInfo(location).GetFiles("*.*", SearchOption.AllDirectories).Sum(file => file.Length);
    }
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);