방법: 확장명에 따라 파일 그룹화(LINQ)
이 예제에서는 LINQ를 사용하여 파일 또는 폴더 목록에서 고급 그룹화 및 정렬 작업을 수행할 수 있는 방법을 보여 줍니다.또한 Skip<TSource> 및 Take<TSource> 메서드를 사용하여 콘솔 창에서 출력을 페이징하는 방법을 보여 줍니다.
예제
다음 쿼리에서는 파일 확장명을 사용하여 지정한 디렉터리 트리의 콘텐츠를 그룹화하는 방법을 보여 줍니다.
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;
}
}
}
이 프로그램의 출력은 로컬 파일 시스템의 세부 사항과 startFolder가 설정된 내용에 따라 길어질 수 있습니다.모든 결과를 볼 수 있도록 이 예제에서는 결과를 통해 페이징하는 방법을 보여 줍니다.같은 기술을 Windows 및 웹 응용 프로그램에 적용할 수 있습니다.코드에서는 그룹의 항목을 페이징하므로 중첩된 foreach 루프가 필요합니다.또한 목록에서 현재 위치를 계산하고 사용자가 페이징을 중지하고 프로그램을 종료할 수 있는 몇 가지 추가 논리가 있습니다.이 경우 페이징 쿼리는 원래 쿼리에서 캐시된 결과에 대해 실행됩니다.다른 컨텍스트에서는 LINQ to SQL와 같은 캐싱이 필요하지 않습니다.
코드 컴파일
.NET Framework 버전 3.5를 대상으로 하는 Visual Studio 프로젝트를 만듭니다.기본적으로 프로젝트에는 System.Core.dll에 대한 참조 및 System.Linq 네임스페이스에 대한 using 지시문(C#) 또는 Imports 문(Visual Basic)이 있습니다.C# 프로젝트에서는 System.IO 네임스페이스에 대한 using 지시문을 추가합니다.
프로젝트에 이 코드를 복사합니다.
F5 키를 눌러 프로그램을 컴파일하고 실행합니다.
아무 키나 눌러 콘솔 창을 닫습니다.
강력한 프로그래밍
여러 형식의 문서와 파일의 콘텐츠에서 많이 수행되는 쿼리 작업의 경우 Windows Desktop Search 엔진을 사용해 보십시오.