Procedura: eseguire una query per trovare il numero totale di byte in un set di cartelle (LINQ)
In questo esempio viene illustrato come recuperare il numero totale di byte utilizzati da tutti i file in una cartella specificata e in tutte le relative sottocartelle.
Esempio
Il metodo Sum aggiunge i valori di tutti gli elementi selezionati nella clausola select. È possibile modificare facilmente questa query per recuperare il file più grande o più piccolo nella struttura ad albero di directory specificata chiamando il metodo Min``1 o Max``1 anziché 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 è necessario contare solo il numero di byte in una struttura ad albero di directory specificata, è possibile eseguire questa operazione in modo più efficiente senza creare una query LINQ che comporta un sovraccarico dovuto alla creazione della raccolta di elenchi come origine dati. I vantaggi dell'utilizzo di LINQ aumentano in base alla complessità della query oppure quando è necessario eseguire più query sulla stessa origine dati.
La query effettua una chiamata a un metodo separato per ottenere la lunghezza del file. Questa operazione viene eseguita per gestire una possibile eccezione generata nel caso in cui il file sia stato eliminato in un altro thread dopo la creazione dell'oggetto FileInfo nella chiamata a GetFiles. Sebbene l'oggetto FileInfo sia già stato creato, l'eccezione può verificarsi poiché un oggetto FileInfo tenta di aggiornare la proprietà Length con la lunghezza più recente al primo accesso alla proprietà. Inserendo questa operazione in un blocco try/catch all'esterno della query, si evita di eseguire operazioni nelle query che possono causare effetti collaterali. In generale, è necessario prestare particolare attenzione durante la gestione delle eccezioni, per assicurarsi che un'applicazione non venga lasciata in uno stato sconosciuto.
Compilazione del codice
Creare un progetto Visual Studio per .NET Framework versione 3.5. Per impostazione predefinita, il progetto include un riferimento a System.Core.dll e una direttiva using (C#) o un'istruzione Imports (Visual Basic) per lo spazio dei nomi System.Linq. Nei progetti C# aggiungere una direttiva using per lo spazio dei nomi System.IO.
Copiare questo codice nel progetto.
Premere F5 per compilare ed eseguire il programma.
Premere un tasto per chiudere la finestra della console.
Programmazione efficiente
Per operazioni di query complesse sul contenuto di più tipi di documenti e file, utilizzare il motore Windows Desktop Search.