次の方法で共有


方法: ディレクトリ ツリー内で最もサイズの大きいファイルを照会する (LINQ)

この例では、ファイル サイズ (バイト単位) に関連する 5 つのクエリを示します。

  • 最大ファイルのサイズをバイト単位で取得する方法

  • 最小ファイルのサイズをバイト単位で取得する方法

  • 指定したルート フォルダーの下にある 1 つ以上のフォルダーから、最大または最小のファイルの 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"

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

        ' 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 fileList _
                         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
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.
        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);

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

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

}

1 つ以上の完全な FileInfo オブジェクトを返すには、クエリで最初にデータ ソースの各要素を調べて、Length プロパティの値を基準に並べ替える必要があります。 その後、単一の要素を返したり、最大のサイズを持つ要素のシーケンスを返したりできます。 First を使用すると、リストの最初の要素を返すことができます。 最初の n 個の要素を返すには、Take<TSource> を使用します。 最も小さい要素をリストの最初に配置するには、降順の並べ替え順序を指定します。

このクエリでは、個別のメソッドを呼び出してファイル サイズ (バイト単位) を取得します。これにより、GetFiles の呼び出しで FileInfo オブジェクトが作成された後、別のスレッドでファイルが削除された場合に発生する可能性のある例外を防ぎます。 FileInfo オブジェクトが既に作成されていても、例外は発生する可能性があります。これは、Length プロパティに最初にアクセスしたときに、FileInfo オブジェクトがこのプロパティを最新のサイズ (バイト単位) で更新しようとするためです。 ここでは、この操作をクエリの外部の try-catch ブロックに配置することで、副作用を引き起こす可能性のある操作をクエリで行わないという規則に従っています。 一般に、例外を処理する場合は、アプリケーションが不明な状態にならないように細心の注意が必要です。

コードのコンパイル

  • .NET Framework Version 3.5 を対象とする Visual Studio プロジェクトを作成します。 プロジェクトには、System.Core.dll への参照と、System.Linq 名前空間に対する using ディレクティブ (C#) または Imports ステートメント (Visual Basic) が既定で含まれます。

  • このコードをプロジェクト内にコピーします。

  • F5 キーを押して、プログラムをコンパイルおよび実行します。

  • 任意のキーを押して、コンソール ウィンドウを終了します。

信頼性の高いプログラミング

複数の種類のドキュメントやファイルの内容を対象に、集中的にクエリ操作を実行する場合は、Windows デスクトップ サーチ エンジンを使用することを検討してください。

参照

概念

LINQ to Objects

LINQ とファイル ディレクトリ