Como: Consulta para o número Total de Bytes em um conjunto de pastas (LINQ)

Este exemplo mostra como recuperar o número total de bytes usado por todos os arquivos em uma pasta especificada e todas as suas subpastas.

Exemplo

O Sum método adiciona os valores de todos os itens selecionados na select cláusula. Você pode modificar facilmente essa consulta para recuperar o arquivo de maior ou menor na árvore de diretório especificado, chamando o Min ou Max método em vez 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;
    }
}

Se você tiver apenas contar o número de bytes em uma árvore de diretório especificado, você pode fazer isso com mais eficiência sem criar um LINQ a consulta, o que gera a sobrecarga de criação da coleção de lista como uma fonte de dados. A utilidade do LINQ abordagem aumenta à medida que a consulta se torna mais complexa, ou quando você precisa executar várias consultas a mesma fonte de dados.

A consulta chama um método separado para obter o comprimento do arquivo. Ele faz isso para consumir a exceções que serão geradas se o arquivo foi excluído em outro thread após a FileInfo objeto foi criado na chamada para GetFiles. Embora o FileInfo objeto já foi criado, a exceção pode ocorrer porque um FileInfo objeto irá tentar atualizar seu Length propriedade com o comprimento de mais atual na primeira vez que a propriedade for acessada. Colocando esta operação em um bloco try-catch fora da consulta, o código segue a regra de evitar operações de consultas podem causar efeitos colaterais. Em geral, ótimo deve ter cuidado ao consumir o exceções para certificar-se de que um aplicativo não é deixado em um estado desconhecido.

Compilando o código

  • Criar um projetoVisual Studio que se destina a.NET Framework versão 3.5. O projeto tem uma referência a System.Core.dll e um using diretiva (C#) ou Imports (Visual Basic) da declaração do namespace System. LINQ por padrão. No C# projetos, adicione um using a diretiva para o namespace System. IO.

  • Copie este código em seu projeto.

  • Pressione F5 para compilar e executar o programa.

  • Pressione qualquer tecla para sair da janela do console.

Programação robusta

Para operações de consulta intensivo sobre o conteúdo de vários tipos de documentos e arquivos, considere o uso de O Windows Desktop Search engine.

Consulte também

Conceitos

LINQ para Objetos

LINQ e os diretórios de arquivos