【问题标题】:How to find the most recent file in a directory using .NET, and without looping?如何使用 .NET 在目录中查找最新文件且不循环?
【发布时间】:2010-11-13 21:04:15
【问题描述】:

我需要在一个目录中找到最近修改的文件。

我知道我可以遍历文件夹中的每个文件并比较 File.GetLastWriteTime,但是有没有更好的方法可以在不循环的情况下做到这一点?

【问题讨论】:

  • 不,没有更好的方法可以避免循环。即使使用 LINQ 也只是将循环隐藏到一些您无法直接看到的更深层次的功能中。
  • 如果您想在整个文件系统上查找最近修改的文件,那么 NTFS 更改日志会很有用。但是,在 C# 中很难使用。

标签: c# .net file loops last-modified


【解决方案1】:

这样的事情怎么样...

var directory = new DirectoryInfo("C:\\MyDirectory");
var myFile = (from f in directory.GetFiles()
             orderby f.LastWriteTime descending
             select f).First();

// or...
var myFile = directory.GetFiles()
             .OrderByDescending(f => f.LastWriteTime)
             .First();

【讨论】:

  • 个人觉得不加糖的版本更容易阅读:directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First()
  • 是的,我也同意大部分时间 - 但是在给出示例时,查询语法使它更明显的是它是一个 linq 查询。我将使用两个选项更新示例以进行澄清。
  • 谢谢!现在我只需要说服我的老板加快从 .net 2.0 升级我们的过程,这样我就可以使用 Linq :)
  • 您可以将 linq 与 2.0 SP1 一起使用,但需要做一些额外的工作 - 只需引用 3.5 中的 System.Core.dll 文件,并将其设置为“复制本地”
  • 不应该使用FirstOrDefault() 而不是First() 吗?如果目录为空,后者将导致InvalidOperationException
【解决方案2】:

扩展上面的第一个,如果你想搜索某个模式,你可以使用以下代码:

using System.IO;
using System.Linq;
...
string pattern = "*.txt";
var dirInfo = new DirectoryInfo(directory);
var file = (from f in dirInfo.GetFiles(pattern) orderby f.LastWriteTime descending select f).First();

【讨论】:

  • 我需要那个。谢谢。
  • 对于那些可能忘记的人:您必须包含using System.Linq 否则会出现错误。
【解决方案3】:

如果你想递归搜索,可以使用这段漂亮的代码:

public static FileInfo GetNewestFile(DirectoryInfo directory) {
   return directory.GetFiles()
       .Union(directory.GetDirectories().Select(d => GetNewestFile(d)))
       .OrderByDescending(f => (f == null ? DateTime.MinValue : f.LastWriteTime))
       .FirstOrDefault();                        
}

只要这样称呼它:

FileInfo newestFile = GetNewestFile(new DirectoryInfo(@"C:\directory\"));

就是这样。如果目录为空,则返回 FileInfo 实例或 null

【讨论】:

【解决方案4】:

非 LINQ 版本:

/// <summary>
/// Returns latest writen file from the specified directory.
/// If the directory does not exist or doesn't contain any file, DateTime.MinValue is returned.
/// </summary>
/// <param name="directoryInfo">Path of the directory that needs to be scanned</param>
/// <returns></returns>
private static DateTime GetLatestWriteTimeFromFileInDirectory(DirectoryInfo directoryInfo)
{
    if (directoryInfo == null || !directoryInfo.Exists)
        return DateTime.MinValue;

    FileInfo[] files = directoryInfo.GetFiles();
    DateTime lastWrite = DateTime.MinValue;

    foreach (FileInfo file in files)
    {
        if (file.LastWriteTime > lastWrite)
        {
            lastWrite = file.LastWriteTime;
        }
    }

    return lastWrite;
}

/// <summary>
/// Returns file's latest writen timestamp from the specified directory.
/// If the directory does not exist or doesn't contain any file, null is returned.
/// </summary>
/// <param name="directoryInfo">Path of the directory that needs to be scanned</param>
/// <returns></returns>
private static FileInfo GetLatestWritenFileFileInDirectory(DirectoryInfo directoryInfo)
{
    if (directoryInfo == null || !directoryInfo.Exists)
        return null;

    FileInfo[] files = directoryInfo.GetFiles();
    DateTime lastWrite = DateTime.MinValue;
    FileInfo lastWritenFile = null;

    foreach (FileInfo file in files)
    {
        if (file.LastWriteTime > lastWrite)
        {
            lastWrite = file.LastWriteTime;
            lastWritenFile = file;
        }
    }
    return lastWritenFile;
}

【讨论】:

  • 对不起,没有看到你不想循环的事实。无论如何...也许它会帮助某人搜索类似的东西
  • 此代码无法编译。 - lastUpdatedFile 不应该是一个数组。 - lastUpdate 的初始值无效(0001/0/0)。
【解决方案5】:

简短而简单

new DirectoryInfo(path).GetFiles().OrderByDescending(o => o.LastWriteTime).FirstOrDefault();

【讨论】:

    【解决方案6】:

    如果您使用 Directory.EnumerateFiles 并希望读取最新修改的文​​件,则另一种方法。

    foreach (string file in Directory.EnumerateFiles(fileDirectory, fileType).OrderByDescending(f => new FileInfo(f).LastWriteTime))
    
    }
    

    【讨论】:

      【解决方案7】:

      您可以使用FileSystemWatcher 对新的文件活动做出反应。

      【讨论】:

      • 它不起作用,因为在他的应用程序未运行时可以修改文件。
      • 他没有提供那种细节......我们怎么知道它不是一个持久应用?
      • 我们没有,但 Scott 有一个更好的解决方案,适用于这两种情况。
      • 另外,请注意 FSW 不适用于大多数网络共享文件夹。
      【解决方案8】:

      有点晚了,但是……

      由于list&lt;FileInfo&gt; lastUpdateFile = null;,您的代码将无法运行 后来lastUpdatedFile.Add(file); 所以会抛出NullReference 异常。 工作版本应该是:

      private List<FileInfo> GetLastUpdatedFileInDirectory(DirectoryInfo directoryInfo)
      {
          FileInfo[] files = directoryInfo.GetFiles();
          List<FileInfo> lastUpdatedFile = new List<FileInfo>();
          DateTime lastUpdate = DateTime.MinValue;
          foreach (FileInfo file in files)
          {
              if (file.LastAccessTime > lastUpdate)
              {
                  lastUpdatedFile.Add(file);
                  lastUpdate = file.LastAccessTime;
              }
          }
      
          return lastUpdatedFile;
      }
      

      谢谢

      【讨论】:

        【解决方案9】:

        这是一个从每个子目录中获取最新文件的版本

        List<string> reports = new List<string>();    
        DirectoryInfo directory = new DirectoryInfo(ReportsRoot);
        directory.GetFiles("*.xlsx", SearchOption.AllDirectories).GroupBy(fl => fl.DirectoryName)
        .ForEach(g => reports.Add(g.OrderByDescending(fi => fi.LastWriteTime).First().FullName));
        

        【讨论】:

          【解决方案10】:
          private List<FileInfo> GetLastUpdatedFileInDirectory(DirectoryInfo directoryInfo)
          {
              FileInfo[] files = directoryInfo.GetFiles();
              List<FileInfo> lastUpdatedFile = null;
              DateTime lastUpdate = new DateTime(1, 0, 0);
              foreach (FileInfo file in files)
              {
                  if (file.LastAccessTime > lastUpdate)
                  {
                      lastUpdatedFile.Add(file);
                      lastUpdate = file.LastAccessTime;
                  }
              }
          
              return lastUpdatedFile;
          }
          

          【讨论】:

            【解决方案11】:

            我这样做是一堆我的应用程序,我使用这样的声明:

              var inputDirectory = new DirectoryInfo("\\Directory_Path_here");
              var myFile = inputDirectory.GetFiles().OrderByDescending(f => f.LastWriteTime).First();
            

            从这里您将在“inputDirectory”变量的目录中获得最近保存/添加/更新的文件的文件名。现在你可以访问它并用它做你想做的事了。

            希望对您有所帮助。

            【讨论】:

            • 补充一点,如果您的目标是取回文件路径,并且您使用 FirstOrDefault 因为可能没有结果,您可以在全名属性。这将为您的路径返回“null”,而无需在调用 FullName 之前从 FirstOrDefault 中保存 FileInfo。 string path = new DirectoryInfo(path).GetFiles().OrderByDescending(o => o.LastWriteTime).FirstOrDefault()?.FullName;
            猜你喜欢
            • 2021-01-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-25
            • 1970-01-01
            • 1970-01-01
            • 2011-06-01
            相关资源
            最近更新 更多