Share via


Comment : regrouper des fichiers par extension (LINQ)

Cet exemple montre comment LINQ peut être utilisé pour effectuer des opérations avancées de regroupement et de tri sur des listes de fichiers ou de dossiers.Il montre également comment parcourir les résultats dans la fenêtre de console à l'aide des méthodes Skip<TSource> et Take<TSource>.

Exemple

La requête suivante montre comment regrouper le contenu d'une arborescence de répertoires spécifiée par l'extension de nom de fichier.

Module GroupByExtension
    Public Sub Main()

        ' Root folder to query, along with all subfolders.
        Dim startFolder As String = "C:\program files\Microsoft Visual Studio 9.0\VB\"

        ' Used in WriteLine() to skip over startfolder in output lines.
        Dim rootLength As Integer = startFolder.Length

        'Take a snapshot of the folder contents
        Dim dir As New System.IO.DirectoryInfo(startFolder)
        Dim fileList = dir.GetFiles("*.*", System.IO.SearchOption.AllDirectories)

        ' Create the query.
        Dim queryGroupByExt = From file In fileList _
                          Group By file.Extension.ToLower() Into fileGroup = Group _
                          Order By ToLower _
                          Select fileGroup

        ' Execute the query. By storing the result we can
        ' page the display with good performance.
        Dim groupByExtList = queryGroupByExt.ToList()

        ' Display one group at a time. If the number of 
        ' entries is greater than the number of lines
        ' in the console window, then page the output.
        Dim trimLength = startFolder.Length
        PageOutput(groupByExtList, trimLength)

    End Sub

    ' Pages console diplay for large query results. No more than one group per page.
    ' This sub specifically works with group queries of FileInfo objects
    ' but can be modified for any type.
    Sub PageOutput(ByVal groupQuery, ByVal charsToSkip)

        ' "3" = 1 line for extension key + 1 for "Press any key" + 1 for input cursor.
        Dim numLines As Integer = Console.WindowHeight - 3
        ' Flag to indicate whether there are more results to diplay
        Dim goAgain As Boolean = True

        For Each fg As IEnumerable(Of System.IO.FileInfo) In groupQuery
            ' Start a new extension at the top of a page.
            Dim currentLine As Integer = 0

            Do While (currentLine < fg.Count())
                Console.Clear()
                Console.WriteLine(fg(0).Extension)

                ' Get the next page of results
                ' No more than one filename per page
                Dim resultPage = From file In fg _
                                Skip currentLine Take numLines

                ' Execute the query. Trim the display output.
                For Each line In resultPage
                    Console.WriteLine(vbTab & line.FullName.Substring(charsToSkip))
                Next

                ' Advance the current position
                currentLine = numLines + currentLine

                ' Give the user a chance to break out of the loop
                Console.WriteLine("Press any key for next page or the 'End' key to exit.")
                Dim key As ConsoleKey = Console.ReadKey().Key
                If key = ConsoleKey.End Then
                    goAgain = False
                    Exit For
                End If
            Loop
        Next
    End Sub
End Module
class GroupByExtension
{
    // This query will sort all the files under the specified folder
    //  and subfolder into groups keyed by the file extension.
    private static void Main()
    {
        // Take a snapshot of the file system.
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\Common7";

        // Used in WriteLine to trim output lines.
        int trimLength = startFolder.Length;

        // Take a snapshot of the file system.
        System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(startFolder);

        // This method assumes that the application has discovery permissions
        // for all folders under the specified path.
        IEnumerable<System.IO.FileInfo> fileList = dir.GetFiles("*.*", System.IO.SearchOption.AllDirectories);

        // Create the query.
        var queryGroupByExt =
            from file in fileList
            group file by file.Extension.ToLower() into fileGroup
            orderby fileGroup.Key
            select fileGroup;

        // Display one group at a time. If the number of 
        // entries is greater than the number of lines
        // in the console window, then page the output.
        PageOutput(trimLength, queryGroupByExt);
    }

    // This method specifically handles group queries of FileInfo objects with string keys.
    // It can be modified to work for any long listings of data. Note that explicit typing
    // must be used in method signatures. The groupbyExtList parameter is a query that produces
    // groups of FileInfo objects with string keys.
    private static void PageOutput(int rootLength,
                                    IEnumerable<System.Linq.IGrouping<string, System.IO.FileInfo>> groupByExtList)
    {
        // Flag to break out of paging loop.
        bool goAgain = true;

        // "3" = 1 line for extension + 1 for "Press any key" + 1 for input cursor.
        int numLines = Console.WindowHeight - 3;

        // Iterate through the outer collection of groups.
        foreach (var filegroup in groupByExtList)
        {
            // Start a new extension at the top of a page.
            int currentLine = 0;

            // Output only as many lines of the current group as will fit in the window.
            do
            {
                Console.Clear();
                Console.WriteLine(filegroup.Key == String.Empty ? "[none]" : filegroup.Key);

                // Get 'numLines' number of items starting at number 'currentLine'.
                var resultPage = filegroup.Skip(currentLine).Take(numLines);

                //Execute the resultPage query
                foreach (var f in resultPage)
                {
                    Console.WriteLine("\t{0}", f.FullName.Substring(rootLength));
                }

                // Increment the line counter.
                currentLine += numLines;

                // Give the user a chance to escape.
                Console.WriteLine("Press any key to continue or the 'End' key to break...");
                ConsoleKey key = Console.ReadKey().Key;
                if (key == ConsoleKey.End)
                {
                    goAgain = false;
                    break;
                }
            } while (currentLine < filegroup.Count());

            if (goAgain == false)
                break;
        }
    }
}

La sortie de ce programme peut être longue, selon les détails du système de fichiers local et la valeur de startFolder.Pour activer l'affichage de tous les résultats, cet exemple indique comment parcourir les résultats.Les mêmes techniques sont applicables aux applications Windows et Web.Notez qu'une boucle foreach imbriquée est requise car le code organise les éléments en groupe.Il existe également une logique supplémentaire pour calculer la position actuelle dans la liste et permettre à l'utilisateur d'arrêter la pagination et de quitter le programme.Dans ce cas particulier, la requête de pagination est exécutée sur les résultats mis en cache à partir de la requête d'origine.Dans d'autres cas, comme LINQ to SQL, une telle mise en cache n'est pas requise.

Compilation du code

  • Créez un projet Visual Studio qui cible .NET Framework version 3.5.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