Share via


Comment : rechercher le nombre total d'octets dans un ensemble de dossiers (LINQ)

Mise à jour : novembre 2007

Cet exemple indique comment récupérer le nombre total d'octets utilisé par tous les fichiers dans un dossier spécifié et tous ses sous-dossiers.

Exemple

La méthode Sum ajoute les valeurs de tous les éléments sélectionnés dans la clause select. Vous pouvez facilement modifier cette requête pour récupérer le fichier le plus grand ou le plus petit dans l'arborescence spécifiée en appelant la méthode Min ou Max au lieu de Sum.

Module QueryTotalBytes
    Sub Main()

        ' Change the drive\path if necessary.
        Dim root As String = "C:\Program Files\Microsoft Visual Studio 9.0\VB"

        'Take a snapshot of the folder contents.
        ' This method assumes that the application has discovery permissions
        ' for all folders under the specified path.
        Dim fileList = My.Computer.FileSystem.GetFiles _
                  (root, FileIO.SearchOption.SearchAllSubDirectories, "*.*")

        Dim fileQuery = From file In fileList _
                        Select GetFileLength(file)

        ' Force execution and cache the results to avoid multiple trips to the file system.
        Dim fileLengths = fileQuery.ToArray()

        ' Find the largest file
        Dim maxSize = Aggregate aFile In fileLengths Into Max()

        ' Find the total number of bytes
        Dim totalBytes = Aggregate aFile In fileLengths Into Sum()

        Console.WriteLine("The largest file is " & maxSize & " bytes")
        Console.WriteLine("There are " & totalBytes & " total bytes in " & _
                          fileList.Count & " files under " & root)

        ' Keep the console window open in debug mode
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub

    ' This method is used to catch the possible exception
    ' that can be raised when accessing the FileInfo.Length property.
    Function GetFileLength(ByVal filename As String) As Long
        Dim retval As Long
        Try
            Dim fi As New System.IO.FileInfo(filename)
            retval = fi.Length
        Catch ex As System.IO.FileNotFoundException
            ' If a file is no longer present,
            ' just return zero bytes. 
            retval = 0
        End Try

        Return retval
    End Function
End Module
class QuerySize
{
    public static void Main()
    {
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\VC#";

        // Take a snapshot of the file system.
        // This method assumes that the application has discovery permissions
        // for all folders under the specified path.
        IEnumerable<string> fileList = System.IO.Directory.GetFiles(startFolder, "*.*", System.IO.SearchOption.AllDirectories);

        var fileQuery = from file in fileList
                        select GetFileLength(file);

        // Cache the results to avoid multiple trips to the file system.
        long[] fileLengths = fileQuery.ToArray();

        // Return the size of the largest file
        long largestFile = fileLengths.Max();

        // Return the total number of bytes in all the files under the specified folder.
        long totalBytes = fileLengths.Sum();

        Console.WriteLine("There are {0} bytes in {1} files under {2}",
            totalBytes, fileList.Count(), startFolder);
        Console.WriteLine("The largest files is {0} bytes.", largestFile);

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

    // This method is used to swallow the possible exception
    // that can be raised when accessing the System.IO.FileInfo.Length property.
    static long GetFileLength(string filename)
    {
        long retval;
        try
        {
            System.IO.FileInfo fi = new System.IO.FileInfo(filename);
            retval = fi.Length;
        }
        catch (System.IO.FileNotFoundException)
        {
            // If a file is no longer present,
            // just add zero bytes to the total.
            retval = 0;
        }
        return retval;
    }
}

Si vous devez seulement compter le nombre d'octets dans une arborescence spécifiée, vous pouvez le faire de façon plus efficace sans créer de requête LINQ, ce qui provoque une charge mémoire due à la création de la collection de listes comme source de données. L'approche LINQ devient plus utile lorsque la requête devient plus complexe ou lorsque vous devez exécuter plusieurs requêtes sur la même source de données.

La requête appelle une méthode séparée pour obtenir la longueur du fichier. Elle effectue cette opération pour utiliser l'exception potentielle qui sera levée si le fichier a été supprimé sur un autre thread après la création de l'objet FileInfo lors de l'appel à GetFiles. Même si l'objet FileInfo a déjà été créé, l'exception peut se produire car un objet FileInfo essaie d'actualiser sa propriété Length avec la longueur la plus récente lors du premier accès à la propriété. En mettant cette opération dans un bloc try-catch à l'extérieur de la requête, le code suit la règle consistant à éviter les opérations dans les requêtes qui peuvent provoquer des effets secondaires. En général, il est recommandé d'être particulièrement vigilant lors de l'utilisation des exceptions afin de s'assurer que l'état d'une application n'est pas inconnu.

Compilation du code

  • Créez un projet Visual Studio qui cible la version 3.5 du .NET Framework. Par défaut, le projet possède une référence à System.Core.dll et une directive using (C#) ou une instruction Imports (Visual Basic) pour l'espace de noms System.Linq. Dans les projets C#, ajoutez une directive using pour l'espace de noms System.IO.

  • Copiez ce code dans votre projet.

  • Appuyez sur F5 pour compiler et exécuter le programme.

  • Appuyez sur une touche pour quitter la fenêtre de console.

Programmation fiable

Pour les opérations de requête intensives sur le contenu de plusieurs types de documents et de fichiers, envisagez d'utiliser le moteur de recherche Windows Desktop Search (en anglais).

Voir aussi

Concepts

LINQ to Objects

LINQ et répertoires de fichiers