如何:查詢一組資料夾中的位元組總數 (LINQ)
這個範例顯示如何擷取所指定資料夾及其所有子資料夾中之所有檔案使用的位元組總數。
範例
Sum 方法會加入 select 子句中選取之所有項目的值。 您可以輕鬆修改這個查詢,以呼叫 Min``1 或 Max``1 方法 (而非 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;
}
}
如果您只需要計算所指定目錄樹狀結構中的位元組數,則可以用更有效率的方式進行這項作業,而不需要建立 LINQ 查詢,原因是這種查詢需要多花時間來建立清單集合做為資料來源。 當查詢越複雜,或需要對相同資料來源執行多個查詢時,LINQ 方式就越有用。
查詢會呼叫外面另一個方法來取得檔案長度。 這麼做是要解決可能會因下列狀況引發的例外狀況 (Exception):自呼叫 GetFiles 而建立 FileInfo 物件後,有另一個執行緒刪除了檔案。 即使已建立 FileInfo,還是可能會發生這個例外狀況,原因是 FileInfo 物件會在它的 Length 屬性第一次受到存取時,嘗試用目前最新的長度來重新整理這個屬性。 讓這個作業進入查詢外部的 try-catch 區塊,程式碼就會遵循規則,以避免查詢中會造成副作業的作業。 一般而言,處理例外狀況時需要十分小心,以確定應用程式不是處於未知狀態。
編譯程式碼
建立以 .NET Framework 3.5 版為目標的 Visual Studio 專案。 此專案預設包含 System.Core.dll 的參考,以及 System.Linq 命名空間 (Namespace) 的 using 指示詞 (C#) 或 Imports 陳述式 (Visual Basic)。 請在 C# 專案中,加入 System.IO 命名空間的 using 指示詞。
請將這段程式碼複製到您的專案,
按 F5 編譯和執行程式。
按任何鍵離開主控台視窗。
穩固程式設計
如需對多種類型的文件和檔案內容執行大量查詢作業,可考慮使用 Windows 桌面搜尋引擎。