【问题标题】:Get File Count but not file name, for particular date获取特定日期的文件计数但不获取文件名
【发布时间】:2015-06-05 05:11:43
【问题描述】:

我有这个功能,用于读取联系数十万个文件的目录并获取特定日期的文件数。有没有办法根据提供的日期使用搜索/计数模式?

这工作正常,但需要的时间太长。有没有更好的办法?

我正在使用 VS 2008(我的客户端 m/c。我无法升级框架或 VS)

 public static int GetFileCount(DirectoryInfo filePath)
    {
        int requestCount = 0;
        int day = -1;

        FileInfo[] files = filePath.GetFiles();

        DateTime minDate = DateTime.Today.AddDays(day);
        DateTime maxDate = DateTime.Today;
        DateTime lastWriteTime = DateTime.MinValue;


        foreach (FileInfo file in files)
        {
            if (file.LastWriteTime < maxDate && file.LastWriteTime > minDate)
            {
                requestCount++;
                //lastWriteTime = file.LastWriteTime;
            }
        }

        return requestCount;
    }

【问题讨论】:

  • @ZoharPeled - 建议永远不能重复,我希望文件数超过十万个文件。事实上,我上面的代码工作正常。但我期待有关如何使这更快的建议。我上面的代码需要很长时间才能给出计数值。所以任何关于优化我上面的帮助都是最重要的
  • @ZoharPeled :如果您有我的担忧,请请求将我的问题从重复提及中删除
  • 抱歉,但我看不出您的问题与我所链接的问题有何显着不同。您想根据LastWriteTime 搜索文件,我链接到的问题是根据CreationTime 搜索文件。这是我看到的唯一区别,而且不是很显着。
  • 事情是我希望通过跟踪数千个文件来使我的代码更快地得到结果。

标签: c# .net


【解决方案1】:

更高效一点的是使用EnumerateFiles,例如使用LINQ:

int requestCount = filePath.EnumerateFiles()
    .Count(file => file.LastWriteTime < maxDate && file.LastWriteTime >= minDate);

EnumerateFilesGetFiles 方法的区别如下: 使用EnumerateFiles,就可以开始枚举名字的集合了 在返回整个集合之前;当你使用GetFiles 时,你 必须等待返回整个名称数组才能 访问数组。因此,当您处理多个文件并且 目录,EnumerateFiles 可以更高效

但是,您为什么要将DateTime 转换为String,然后又转换为ConvertToDateTime?而不是Convert.ToDateTime(DateTime.Now.ToShortDateString()),你只需要:DateTime.Today,所以:

DateTime minDate = DateTime.Today.AddDays(day);
DateTime maxDate = DateTime.Today;

如果您不能使用 .NET4,则不能使用 EnumerateFilesit's not easy to get the same lazy load behaviour。您仍然可以使用 LINQ 方法以获得更好的可读性。

【讨论】:

  • 我对框架有限制,即我的客户端只有 3.5 版本。所以我手残,不能使用 EnumerateFiles() 功能。参考:stackoverflow.com/questions/4888836/…
  • @user1093452: 那么你不能使用EnumerateFiles 并且没有简单的方法来模拟它。但是,您为什么要将DateTime 转换为String,然后又转换为ConvertToDateTime?而不是Convert.ToDateTime(DateTime.Now.ToShortDateString()),您只需要:DateTime.Today;。我已经编辑了我的答案。
【解决方案2】:

如果您有 3.5 .NET 框架约束,试试这个

public static int GetFileCount(DirectoryInfo filePath)
    {
        int requestCount = 0;
DirectoryInfo info = new DirectoryInfo(filePath);
        DateTime minDate = Convert.ToDateTime(DateTime.Now.AddDays(day).ToShortDateString());
        DateTime maxDate = Convert.ToDateTime(DateTime.Now.ToShortDateString());
        DateTime lastWriteTime = DateTime.MinValue;

requestCount = info.GetFiles().Select(x => (x.LastWriteTime >= minDate  && x.LastWriteTime <= maxDate)).Count();


        return requestCount;
    }

【讨论】:

  • @TimSchmelter:你是对的。性能没有任何变化
【解决方案3】:

我建议您将文件数组分解为 2/4/8 个列表(取决于您拥有的处理器数量,即双处理器 - 2、四处理器 - 4、八处理器 - 8)。然后产生 2/4/8 个线程,并为每个线程提供自己的列表进行处理,然后当所有线程完成各自的处理时,组合结果并将其显示给最终用户。

注意:此解决方案将加速您的解决方案,但不会快 2 倍/4 倍/8 倍,因为此解决方案可能听起来像。磁盘 IO 会影响执行时间的持续时间。

【讨论】:

  • 感谢您的意见
【解决方案4】:

我之前也遇到过类似的问题,并且在某些情况下能够将处理时间缩短多达 10 倍。我所做的是在这里使用 FindFile 方法:https://code.google.com/p/csharptest-net/source/browse/src/Library/IO/FindFile.cs

此外,在系统上禁用 8.3 文件名。相关链接:https://support.microsoft.com/en-us/kb/130694

启用 8.3 文件名可能会在某些情况下影响性能。我在上面链接的 Microsoft 知识库文章描述了这个问题。除了禁用 8.3 文件名之外,您还必须修改系统上的现有文件。我所做的是将它们全部移动到临时目录,然后返回。禁用 8.3 文件名可防止新文件获得分配给它的 8.3 文件名,但现有文件仍将拥有它。

执行上述步骤后,我注意到性能有所提高。我有一些包含超过 500k 文件的文件夹需要将近 2 个小时来迭代和处理,但是有了这个,我只花了大约 5 分钟。

【讨论】:

    猜你喜欢
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2015-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多