当前位置:  开发笔记 > 编程语言 > 正文

在.NET中计算目录大小的最佳方法是什么?

如何解决《在.NET中计算目录大小的最佳方法是什么?》经验,为你挑选了7个好方法。

我已编写以下例程来手动遍历目录并在C#/ .NET中计算其大小:


protected static float CalculateFolderSize(string folder)
{
    float folderSize = 0.0f;
    try
    {
        //Checks if the path is valid or not
        if (!Directory.Exists(folder))
            return folderSize;
        else
        {
            try
            {
                foreach (string file in Directory.GetFiles(folder))
                {
                    if (File.Exists(file))
                    {
                        FileInfo finfo = new FileInfo(file);
                        folderSize += finfo.Length;
                    }
                }

                foreach (string dir in Directory.GetDirectories(folder))
                    folderSize += CalculateFolderSize(dir);
            }
            catch (NotSupportedException e)
            {
                Console.WriteLine("Unable to calculate folder size: {0}", e.Message);
            }
        }
    }
    catch (UnauthorizedAccessException e)
    {
        Console.WriteLine("Unable to calculate folder size: {0}", e.Message);
    }
    return folderSize;
}

我有一个应用程序,它为大量文件夹重复运行此例程.我想知道是否有更有效的方法来计算.NET文件夹的大小?我没有在框架中看到任何具体内容.我应该使用P/Invoke和Win32 API吗?在.NET中计算文件夹大小的最有效方法是什么?



1> hao..:

不,这看起来像计算目录大小的推荐方法,相关方法包括如下:

public static long DirSize(DirectoryInfo d) 
{    
    long size = 0;    
    // Add file sizes.
    FileInfo[] fis = d.GetFiles();
    foreach (FileInfo fi in fis) 
    {      
        size += fi.Length;    
    }
    // Add subdirectory sizes.
    DirectoryInfo[] dis = d.GetDirectories();
    foreach (DirectoryInfo di in dis) 
    {
        size += DirSize(di);   
    }
    return size;  
}

您可以使用root调用:

Console.WriteLine("The size is {0} bytes.", DirSize(new DirectoryInfo(targetFolder));

... targetFolder要计算的文件夹大小在哪里.


使用EnumerateFiles和EnumerateDirectories

2> Mike Thompso..:

我不相信有一个Win32 API来计算目录所占用的空间,虽然我有必要对此进行更正.如果有的话我会假设资源管理器会使用它.如果在资源管理器中获取大型目录的属性,则为您提供文件夹大小所需的时间与其包含的文件/子目录的数量成正比.

你的日常工作看起来相当简洁.请记住,您正在计算文件长度的总和,而不是磁盘上消耗的实际空间.群集,文件流等末尾的浪费空间所占用的空间将被忽略.


此方法还会忽略联结,硬链接,压缩和脱机存储.

3> Trikaldarshi..:

可以遵循最佳和最短的一种班轮方式

  long length = Directory.GetFiles(directoryPath,"*",SearchOption.AllDirectories).Sum(t => (new FileInfo(t).Length));



4> Mehrdad..:

真正的问题是,你打算用这个尺码做什么?

您的第一个问题是"文件大小" 至少有四个定义:

"文件结束"偏移量,即从文件的开头到结尾必须跳过的字节数.
换句话说,它是文件中逻辑上的字节数(从使用角度来看).

"有效数据长度",等于实际未存储的第一个字节的偏移量.
这始终小于或等于"文件结尾",并且是簇大小的倍数.
例如,1 GB文件的有效数据长度为1 MB.如果您要求Windows读取前8 MB,它将读取前1 MB并假装其余数据存在,并将其作为零返回.

文件的"已分配大小".这始终大于或等于"文件结尾".
这是操作系统为文件分配的簇数乘以簇大小.
与"文件结尾"大于"有效数据长度"的情况不同,多余的字节被视为文件数据的一部分,因此如果您尝试读取,操作系统将不会用零填充缓冲区超出文件末尾的已分配区域.

文件的"压缩大小",仅对压缩(和稀疏?)文件有效.
它等于群集的大小,乘以实际分配给此文件的卷上的群集数.
对于非压缩和非稀疏文件,没有"压缩大小"的概念; 你会用"分配大小"代替.

你的第二个问题是像"文件"一样C:\Foo实际上可以有多个数据流.
此名称仅指默认流.一个文件可能有备用流,比如C:\Foo:Bar,其大小甚至没有在资源管理器中显示!

你的第三个问题是"文件"可以有多个名称("硬链接").
例如,C:\Windows\notepad.exe并且C:\Windows\System32\notepad.exe是两个名称相同文件. 任何名称都可用于打开文件的任何流.

你的第四个问题是"文件"(或目录)实际上甚至可能不是文件(或目录):
它可能是某个其他文件的软链接("符号链接"或"重新分析点")(或目录).
那个其他文件甚至可能不在同一个驱动器上.它甚至可能指向网络上的某些东西,或者它甚至可能是递归的!如果它是递归的,大小应该是无限的吗?

你的第五个是有"过滤器"驱动程序,使某些文件或目录看起来像实际文件或目录,即使它们不是.例如,微软的WIM映像文件(被压缩),可以使用一种称为ImageX工具文件夹中的"安装",而那些没有像重分析点或链接.它们看起来就像目录 - 除了它们实际上不是目录,而"大小"的概念对它们来说并没有意义.

您的第六个问题是每个文件都需要元数据.
例如,对同一文件具有10个名称需要更多元数据,这需要空间.如果文件名很短,那么拥有10个名称可能与拥有1个名称一样便宜 - 如果它们很长,那么拥有多个名称可以为元数据使用更多的磁盘空间.(同一个故事有多个流等等)
你也算这些吗?



5> Grozz..:
public static long DirSize(DirectoryInfo dir)
{
    return dir.GetFiles().Sum(fi => fi.Length) +
           dir.GetDirectories().Sum(di => DirSize(di));
}


`PathTooLongException`(见[blogpost](http://blogs.msdn.com/b/bclteam/archive/2007/02/13/long-paths-in-net-part-1-of-3-kim- hamilton.aspx))和缺少凭证从某些子目录(`UnauthorizedAccessException`)浮现在脑海中.一个不太重要的问题应该是在运行时拔下可拆卸驱动器(USB Sticks等).这里的异常处理是必须的 - 只需在本地返回0并记录错误(如果求和结果应该是任何值).BTW:在远程共享上应用它可能看起来像DOS攻击.我敢肯定我至少错过了另一个案例:-)
我认为抛弃所有这些情况是可以接受的,因此默认行为很好.`StackOverflowException`是唯一应该处理的,虽然我不相信没有递归符号链接就能达到它.

6> Ahmed Sabry..:
var size = new DirectoryInfo("E:\\").GetDirectorySize();

这是Extension方法背后的代码

public static long GetDirectorySize(this System.IO.DirectoryInfo directoryInfo, bool recursive = true)
{
    var startDirectorySize = default(long);
    if (directoryInfo == null || !directoryInfo.Exists)
        return startDirectorySize; //Return 0 while Directory does not exist.

    //Add size of files in the Current Directory to main size.
    foreach (var fileInfo in directoryInfo.GetFiles())
        System.Threading.Interlocked.Add(ref startDirectorySize, fileInfo.Length);

    if (recursive) //Loop on Sub Direcotries in the Current Directory and Calculate it's files size.
        System.Threading.Tasks.Parallel.ForEach(directoryInfo.GetDirectories(), (subDirectory) =>
    System.Threading.Interlocked.Add(ref startDirectorySize, GetDirectorySize(subDirectory, recursive)));

    return startDirectorySize;  //Return full Size of this Directory.
}



7> Alex..:

更多更快!添加COM引用"Windows脚本宿主对象..."

public double GetWSHFolderSize(string Fldr)
    {
        //Reference "Windows Script Host Object Model" on the COM tab.
        IWshRuntimeLibrary.FileSystemObject FSO = new     IWshRuntimeLibrary.FileSystemObject();
        double FldrSize = (double)FSO.GetFolder(Fldr).Size;
        Marshal.FinalReleaseComObject(FSO);
        return FldrSize;
    }
private void button1_Click(object sender, EventArgs e)
        {
            string folderPath = @"C:\Windows";
        Stopwatch sWatch = new Stopwatch();

        sWatch.Start();
        double sizeOfDir = GetWSHFolderSize(folderPath);
        sWatch.Stop();
        MessageBox.Show("Directory size in Bytes : " + sizeOfDir + ", Time: " + sWatch.ElapsedMilliseconds.ToString());
          }

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有