165 votes

C# trouver le fichier le plus récent dans le répertoire

J'ai besoin de trouver le fichier le plus récemment modifié dans un répertoire.

Je sais que je peux parcourir chaque fichier d'un dossier et comparer File.GetLastWriteTime mais existe-t-il un meilleur moyen de faire cela sans boucle ?

20 votes

Non, il n'y a pas de meilleur moyen d'éviter les boucles. Même l'utilisation de LINQ ne fait que cacher le bouclage dans une fonctionnalité plus profonde où vous ne pouvez pas le voir directement.

2 votes

Si vous voulez trouver le(s) fichier(s) le(s) plus récemment modifié(s) sur l'ensemble du système de fichiers, alors le NTFS Change Journal serait utile. Mais il est très difficile à utiliser en C#.

361voto

Scott Ivey Points 19577

Que diriez-vous de quelque chose comme ça...

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

102 votes

Personnellement, je trouve que la version non sucrée est plus facile à lire : directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First()

6 votes

Oui, je suis aussi d'accord la plupart du temps - mais lorsque je donne des exemples, la syntaxe de la requête rend un peu plus évident qu'il s'agit d'une requête linq. Je vais mettre à jour l'exemple avec les deux options pour clarifier.

3 votes

Merci ! Maintenant, je dois juste convaincre mon patron d'accélérer le processus de mise à niveau de .net 2.0 pour que je puisse utiliser Linq :)

33voto

Zamir Points 51

Si vous souhaitez rechercher un certain modèle, vous pouvez utiliser le code suivant :

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

0 votes

J'avais besoin de ça. Merci.

3 votes

Pour ceux qui l'auraient oublié : vous devez inclure using System.Linq ou bien il y aura une erreur.

21voto

Si vous souhaitez effectuer une recherche récursive, vous pouvez utiliser ce magnifique morceau de code :

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

Il suffit de l'appeler de la manière suivante :

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

et c'est tout. Il retourne un FileInfo ou null si le répertoire est vide.

14 votes

Ou vous pouvez utiliser le recherche récursive option.

10voto

TimothyP Points 6043

Une version non-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;
}

1 votes

Désolé, je n'ai pas vu le fait que vous ne vouliez pas faire de boucle. Quoi qu'il en soit, cela aidera peut-être quelqu'un qui cherche quelque chose de similaire.

3 votes

Ce code ne se compile pas. - lastUpdatedFile ne devrait pas être un tableau. - La valeur initiale de lastUpdate est invalide (0001/0/0).

3voto

Oleg Karbushev Points 1

c'est un peu tard mais...

votre code ne fonctionnera pas, à cause de list<FileInfo> lastUpdateFile = null; et plus tard lastUpdatedFile.Add(file); de sorte que l'exception NullReference sera levée. La version de travail devrait être :

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;
}

Merci

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X