다음을 통해 공유


방법: 디렉터리 트리에서 가장 큰 파일을 하나 이상 쿼리(LINQ)

업데이트: 2007년 11월

이 예제에서는 파일 크기(바이트)와 관련된 5개의 쿼리를 보여 줍니다.

  • 가장 큰 파일의 크기(바이트)를 검색하는 방법

  • 가장 작은 파일의 크기(바이트)를 검색하는 방법

  • 지정한 루트 폴더에 있는 하나 이상의 폴더에서 FileInfo 개체의 가장 큰 파일이나 가장 작은 파일을 검색하는 방법

  • 가장 큰 10개 파일과 같은 시퀀스를 검색하는 방법

  • 지정한 크기보다 작은 파일을 무시하여 파일 크기(바이트)에 따라 파일을 그룹으로 정렬하는 방법

예제

다음 예제에는 파일 크기(바이트)에 따라 파일을 쿼리하고 그룹화하는 방법을 보여 주는 별도의 5개 쿼리가 포함되어 있습니다. 이러한 예제를 쉽게 수정하여 FileInfo 개체의 일부 다른 속성을 기반으로 쿼리할 수 있습니다.

Module QueryBySize
    Sub Main()

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

        Dim fileList = GetFiles(root)

        ' Return the size of the largest file
        Dim maxSize = Aggregate aFile In fileList Into Max(GetFileLength(aFile))

        'Dim maxSize = fileLengths.Max
        Console.WriteLine("The length of the largest file under {0} is {1}", _
                          root, maxSize)

        ' Return the FileInfo object of the largest file
        ' by sorting and selecting from the beginning of the list
        Dim filesByLengDesc = From file In fileList _
                              Let filelength = GetFileLength(file) _
                              Where filelength > 0 _
                              Order By filelength Descending _
                              Select file

        Dim longestFile = filesByLengDesc.First

        Console.WriteLine("The largest file under {0} is {1} with a length of {2} bytes", _
                          root, longestFile.FullName, longestFile.Length)

        Dim smallestFile = filesByLengDesc.Last

        Console.WriteLine("The smallest file under {0} is {1} with a length of {2} bytes", _
                                root, smallestFile.FullName, smallestFile.Length)

        ' Return the FileInfos for the 10 largest files
        ' Based on a previous query, but nothing is executed
        ' until the For Each statement below.
        Dim tenLargest = From file In filesByLengDesc Take 10

        Console.WriteLine("The 10 largest files under {0} are:", root)

        For Each fi As System.IO.FileInfo In tenLargest
            Console.WriteLine("{0}: {1} bytes", fi.FullName, fi.Length)
        Next

        ' Group files according to their size,
        ' leaving out the ones under 200K
        Dim sizeGroups = From file As System.IO.FileInfo In GetFiles(root) _
                         Where file.Length > 0 _
                         Let groupLength = file.Length / 100000 _
                         Group file By groupLength Into fileGroup = Group _
                         Where groupLength >= 2 _
                         Order By groupLength Descending

        For Each group In sizeGroups
            Console.WriteLine(group.groupLength + "00000")

            For Each item As System.IO.FileInfo In group.fileGroup
                Console.WriteLine("   {0}: {1}", item.Name, item.Length)
            Next
        Next

        ' 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.
    ' In this particular case, it is safe to ignore the exception.
    Function GetFileLength(ByVal fi As System.IO.FileInfo) As Long
        Dim retval As Long
        Try
            retval = fi.Length
        Catch ex As FileNotFoundException
            ' If a file is no longer present,
            ' just return zero bytes. 
            retval = 0
        End Try

        Return retval
    End Function

    ' Function to retrieve a list of files. Note that this is a copy
    ' of the file information.
    Function GetFiles(ByVal root As String) As System.Collections.Generic.IEnumerable(Of System.IO.FileInfo)
        Return From file In My.Computer.FileSystem.GetFiles _
                  (root, FileIO.SearchOption.SearchAllSubDirectories, "*.*") _
               Select New System.IO.FileInfo(file)
    End Function
End Module
class QueryBySize
{
    static void Main(string[] args)
    {
        QueryFilesBySize();
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    private static void QueryFilesBySize()
    {
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\";

        // Take a snapshot of the file system. 
        // fileList is an IEnumerable<System.IO.FileInfo>
        var fileList = GetFiles(startFolder);

        //Return the size of the largest file
        long maxSize =
            (from file in fileList
             let len = GetFileLength(file)
             select len)
             .Max();

        Console.WriteLine("The length of the largest file under {0} is {1}",
            startFolder, maxSize);

        // Return the FileInfo object for the largest file
        // by sorting and selecting from beginning of list
        System.IO.FileInfo longestFile = 
            (from file in fileList
            let len = GetFileLength(file)
            where len > 0
            orderby len descending
            select file)
            .First();

        Console.WriteLine("The largest file under {0} is {1} with a length of {2} bytes",
                            startFolder, longestFile.FullName, longestFile.Length);

        //Return the FileInfo of the smallest file
        System.IO.FileInfo smallestFile = 
            (from file in fileList
            let len = GetFileLength(file)
            where len > 0
            orderby len ascending
            select file).First();

        Console.WriteLine("The smallest file under {0} is {1} with a length of {2} bytes",
                            startFolder, smallestFile.FullName, smallestFile.Length);

        //Return the FileInfos for the 10 largest files
        // queryTenLargest is an IEnumerable<System.IO.FileInfo>
        var queryTenLargest = 
            (from file in fileList
            let len = GetFileLength(file)
            orderby len descending
            select file).Take(10);

        Console.WriteLine("The 10 largest files under {0} are:", startFolder);

        foreach (var v in queryTenLargest)
        {
            Console.WriteLine("{0}: {1} bytes", v.FullName, v.Length);
        }


        // Group the files according to their size, leaving out
        // files that are less than 200000 bytes. 
        var querySizeGroups = 
            from file in fileList
            let len = GetFileLength(file)
            where len > 0
            group file by (len / 100000) into fileGroup
            where fileGroup.Key >= 2
            orderby fileGroup.Key descending
            select fileGroup;


        foreach (var filegroup in querySizeGroups)
        {
            Console.WriteLine(filegroup.Key.ToString() + "00000");
            foreach (var item in filegroup)
            {
                Console.WriteLine("\t{0}: {1}", item.Name, item.Length);
            }
        }

        // 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 FileInfo.Length property.
    // In this particular case, it is safe to swallow the exception.
    static long GetFileLength(System.IO.FileInfo fi)
    {
        long retval;
        try
        {
            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;
    }

    // This method assumes that the application has discovery 
    // permissions for all folders under the specified path.
    static IEnumerable<System.IO.FileInfo> GetFiles(string path)
    {
        if (!System.IO.Directory.Exists(path))
            throw new System.IO.DirectoryNotFoundException();

        string[] fileNames = null;
        List<System.IO.FileInfo> files = new List<System.IO.FileInfo>();

        fileNames = System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.AllDirectories);
        foreach (string name in fileNames)
        {
            files.Add(new System.IO.FileInfo(name));
        }
        return files;
    }
}

하나 이상의 전체 FileInfo 개체를 반환하기 위해 쿼리에서 먼저 데이터 소스의 각 개체를 검사한 다음 해당 Length 속성의 값을 기준으로 정렬합니다. 그런 다음 가장 큰 길이의 단일 개체나 시퀀스를 반환할 수 있습니다. First을 사용하여 목록의 첫 번째 요소를 반환합니다. Take<TSource>을 사용하여 처음 n개의 요소를 반환합니다. 목록의 시작 부분에 가장 작은 요소를 놓기 위해 내림차순 정렬을 지정합니다.

쿼리에서는 GetFiles에 대한 호출에서 FileInfo 개체가 생성된 이후 다른 스레드에서 파일이 삭제된 경우 발생할 수 있는 예외를 처리하기 위해 파일 크기(바이트)를 얻는 별도의 메서드를 호출합니다. FileInfo 개체가 이미 생성되었더라도 처음에 Length 속성을 액세스할 때의 최신 크기(바이트)를 사용하여 FileInfo 개체가 해당 속성을 새로 고치려고 하기 때문에 예외가 발생할 수 있습니다. 쿼리 외부에 있는 try-catch 블록에 이 연산을 놓음으로써 예기치 않은 결과를 일으킬 수 있는 쿼리에서 연산을 회피하는 규칙을 따릅니다 응용 프로그램이 알려지지 않은 상태에 놓일 수 있도록 일반적으로 예외를 사용할 때 많은 주의를 기울여야 합니다.

코드 컴파일

  • .NET Framework 버전 3.5를 대상으로 하는 Visual Studio 프로젝트를 만듭니다. 이 프로젝트에는 기본적으로 System.Linq 네임스페이스에 대한 using 지시문(C#) 또는 Imports 문(Visual Basic)과 System.Core.dll에 대한 참조가 있습니다.

  • 프로젝트에 이 코드를 복사합니다.

  • F5 키를 눌러 프로그램을 컴파일하고 실행합니다.

  • 아무 키나 눌러 콘솔 창을 닫습니다.

강력한 프로그래밍

여러 형식의 문서와 파일의 콘텐츠에서 많이 수행되는 쿼리 작업의 경우 Windows Desktop Search 엔진을 사용해 보십시오.

참고 항목

개념

LINQ to Objects

LINQ 및 파일 디렉터리