程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 路徑,文件,目錄,I/O常見操作匯總(二)

路徑,文件,目錄,I/O常見操作匯總(二)

編輯:關於.NET

摘要:

文件操作是程序中非常基礎和重要的內容,而路徑、文件、目錄以及I/O都是在進行文件操作時的常見主題,這裡想把這些常見的問題作個總結,對於每個問題,盡量提供一些解決方案,即使沒有你想要的答案,也希望能提供給你一點有益的思路,如果你有好的建議,懇請能夠留言,使這些內容更加完善。

主要內容:

一、路徑的相關操作, 如判斷路徑是否合法,路徑類型,路徑的特定部分,合並路徑,系統文件夾路徑等內容;

二、相關通用文件對話框,這些對話框可以幫助我們操作文件系統中的文件和目錄;

三、文件、目錄、驅動器的操作,如獲取它們的基本信息,獲取和設置文件和目錄的屬性,文件的版本信息,

搜索文件和目錄,文件判等,復制、移動、刪除、重命名文件和目錄;

四、讀寫文件,包括臨時文件,隨機文件名等;

五、對文件系統的監視;

上一篇介紹了第一、二部分,這一篇介紹一下最重要的第三部分。

三、文件和目錄相關操作

文件和目錄操作涉及的類主要是:FileInfo,DirectoryInfo,DriveInfo,可以認為它們的一個實例對應著一個文件、目錄、驅動器。它們的用法類似,一般是將文件、目錄或驅動器的路徑作為參數傳遞給相應的構造函數創建一個實例,然後訪問它們的屬性和方法。

注意下面幾點:

FileInfo 類和 DirectoryInfo 類都繼承自抽象類 FileSystemInfo , FileSystemInfo 類定義了一些通用的屬性,如 CreationTime 、 Exists 等。但 DriveInfo 類沒有繼承 FileSystemInfo 類,所以它也就沒有上面提到的那些通用屬性了。

FileInfo 類和 DirectoryInfo 類的對象公開的屬性值都是第一次查詢時獲取的值,如果在以此查詢之後文件或目錄發生了改動,就必須調用它們的 Refresh 方法來更新這些屬性。但 DriveInfo 則無需這麼做,它的屬性每次都會讀取文件系統最新的信息。

在創建文件、目錄或驅動器的實例時,如果使用了一個不存在的路徑,並不會報錯,這是你得到一個對象,該對象表示一個並不存在的實體,這意味著它的 Exists 屬性(對於 DriveInfo 來說是 IsReady 屬性)值為 false 。你仍然可以操作該實體,但如果嘗試其它的大多數屬性,就會引發相應的 FileNotFoundException 、 DirectoryNotFoundException 或 DriveNotFoundException 異常。

另外,還可以使用 File / Directory 類,這兩個類的成員都是靜態方法,所以如果只想執行一個操作,那麼使用 File/Directory 中的靜態方法的效率比使用相應的 FileInfo / DirectoryInfo中的 實例方法可能更高。所有的 File / Directory 方法都要求當前所操作的文件 / 目錄的路徑。 注意: File / Directory 類的靜態方法對所有方法都執行安全檢查。如果打算多次重用某個對象,可考慮改用 FileInfo / DirectoryInfo 的相應實例方法,因為並不總是需要安全檢查。

下面是一些常見的問題:

問題1:如何獲取指定文件的基本信息;

解決方案:可以使用FileInfo類的相關屬性:

FileInfo.Exists:獲取指定文件是否存在;

FileInfo.Name,FileInfo.Extensioin:獲取文件的名稱和擴展名;

FileInfo.FullName:獲取文件的全限定名稱(完整路徑);

FileInfo.Directory:獲取文件所在目錄,返回類型為DirectoryInfo;

FileInfo.DirectoryName:獲取文件所在目錄的路徑(完整路徑);

FileInfo.Length:獲取文件的大小(字節數);

FileInfo.IsReadOnly:獲取文件是否只讀;

FileInfo.Attributes:獲取或設置指定文件的屬性,返回類型為FileAttributes枚舉,可以是多個值的組合(見問題2);

FileInfo.CreationTime、FileInfo.LastAccessTime、FileInfo.LastWriteTime:分別用於獲取文件的創建時間、訪問時間、修改時間;

(更多內容還請參考MSDN)

問題2:如何獲取和設置文件的屬性,比如只讀、存檔、隱藏等;

解決方案:

使用FileInfo.Attributes屬性可以獲取和設置文件的屬性,該屬性類型為FileAttributes枚舉,該枚舉的每個值表示一種屬性,FileAttributes枚舉具有屬性(Attribute)FlagsAttribute,所以該枚舉的值可以進行組合,也就是一個文件可以同時擁有多個屬性。下面看看具體的做法:

獲取屬性,比如判斷一個文件是否是只讀的:

// 當文件具有其它屬性時,這種做法會失敗
if (file.Attributes == FileAttributes.ReadOnly)
{
chkReadonly.Checked = true;
}
// 這種寫法就不會有問題了,它只檢查只讀屬性
if ((file.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{
chkReadonly.Checked = true;
}

設置屬性,比如添加和移除一個文件的只讀屬性:

if (chkReadonly.Checked)
{
// 添加只讀屬性
file.Attributes |= FileAttributes.ReadOnly;
}
else
{
// 移除只讀屬性
file.Attributes &= ~FileAttributes.ReadOnly;
}

問題3:如何獲取文件的版本信息(比如版本號,版權聲明,公司名稱等);

解決方案:

使用FileVersionInfo類,該類有大量的版本信息相關的屬性。通過它的靜態方法GetVersionInfo獲得該類的一個實例,然後就可以訪問指定文件的版本信息了,非常方便。如FileVersion表示文件版本號,LegalCopyright表示指定文件的版權聲明,CompanyName表示指定文件的公司名稱。(更多內容還請參考MSDN)

問題4:如何判斷兩個文件的內容是否相同(精確匹配);

解決方案:

使用System.security.Cryptography.HashAlgorithm類為每個文件生成一個哈希碼,然後比較兩個哈希碼是否一致。

在比較文件內容的時候可以采用好幾種方法。例如,檢查文件的某一特定部分是否一致;如果願意,你甚至可以逐字節讀取文件,逐字節進行比較。這兩種方法都是可以的,但在某些情況下,還是使用哈希碼算法更為方便。

該算法為一個文件生成一個小的(通常約為20字節)二進制”指紋”(binary fingerprint)。從統計學角度看,不同的文件不可能生成相同的哈希碼。事實上,即使是一個很小的改動(比如,修改了源文件中的一個bit),也會有50%的幾率來改變哈希碼中的每一個bit。因此,哈希碼常常用於數據安全方面。

要生成一個哈希碼,你必須首先創建一個HashAlgorithm對象,而這通常是調用HashAlgorithm.Create方法來完成的;然後調用HashAlgorithm.ComputeHash方法,它會返回一個存儲哈希碼的字節數組。代碼如下:

/// <summary>
/// 判斷兩個文件內容是否一致
/// </summary>
public static bool IsFilesEqual(string fileName1, string fileName2)
{
using (HashAlgorithm hashAlg = HashAlgorithm.Create())
{
using (FileStream fs1 = new FileStream(fileName1, FileMode.Open), fs2 = new FileStream(fileName2, FileMode.Open))
{
byte[] hashBytes1 = hashAlg.ComputeHash(fs1);
byte[] hashBytes2 = hashAlg.ComputeHash(fs2);
// 比較哈希碼
return (BitConverter.ToString(hashBytes1) == BitConverter.ToString(hashBytes2));
}
}
}

問題5:如何獲取指定目錄的基本信息;

解決方案:可以使用DirectoryInfo類的相關屬性和方法:

DirectoryInfo.Exists:獲取指定目錄是否存在;

DirectoryInfo.Name:獲取目錄的名稱;

DirectoryInfo.FullName:獲取目錄的全限定名稱(完整路徑);

DirectoryInfo.Attributes:獲取或設置指定目錄的屬性,返回類型為FileAttributes枚舉,可以是多個值的組合;

DirectoryInfo.CreationTime、FileInfo.LastAccessTime、FileInfo.LastWriteTime:分別用於獲取目錄的創建時間、訪問時間、修改時間;

DirectoryInfo.Parent:獲取目錄的上級目錄,返回類型為DirectoryInfo;

DirectoryInfo.Root:獲取目錄的根目錄,返回類型為DirectoryInfo;

問題6:如何獲取指定目錄包含的文件和子目錄;

解決方案:

DirectoryInfo.GetFiles():獲取目錄中(不包含子目錄)的文件,返回類型為FileInfo[],支持通配符查找;

DirectoryInfo.GetDirectories():獲取目錄(不包含子目錄)的子目錄,

返回類型為DirectoryInfo[],支持通配符查找;

DirectoryInfo. GetFileSystemInfos():獲取指定目錄下(不包含子目錄)的文件和子目錄,

返回類型為FileSystemInfo[],支持通配符查找;

問題7:如何獲得指定目錄的大小;

解決方案:

檢查目錄內的所有文件,利用FileInfo.Length屬性獲取每個文件的大小,然後進行合計,然後使用遞歸算法處理所有的子目錄的文件,參考下面代碼:

/// <summary>
/// 計算一個目錄的大小
/// </summary>
/// <param name="di">指定目錄</param>
/// <param name="includeSubDir">是否包含子目錄</param>
/// <returns></returns>
private long CalculateDirSize(DirectoryInfo di, bool includeSubDir)
{
long totalSize = 0;
// 檢查所有(直接)包含的文件
FileInfo[] files = di.GetFiles();
foreach (FileInfo file in files)
{
totalSize += file.Length;
}
// 檢查所有子目錄,如果includeSubDir參數為true
if (includeSubDir)
{
DirectoryInfo[] dirs = di.GetDirectories();
foreach (DirectoryInfo dir in dirs)
{
totalSize += CalculateDirSize(dir, includeSubDir);
}
}
return totalSize;
}

問題8:如何使用通配符搜索指定目錄內的所有文件;

解決方案:

使用DirectoryInfo.GetFiles方法的重載版本,它可以接受一個過濾表達式,返回FileInfo數組,另外它的參數還可以指定是否對子目錄進行查找。如:

dir.GetFiles("*.txt", SearchOption.AllDirectories); 問題9:如何復制、移動、重命名、刪除文件和目錄;

解決方案:使用FileInfo和DirectoryInfo類。

下面是FileInfo類的相關方法:

FileInfo.CopyTo:將現有文件復制到新文件,其重載版本還允許覆蓋已存在文件;

FileInfo.MoveTo:將指定文件移到新位置,並提供指定新文件名的選項,所以可以用來重命名文件(而不改變位置); FileInfo.Delete:永久刪除文件,如果文件不存在,則不執行任何操作;

FileInfo.Replace:使用當前FileInfo對象對應文件的內容替換目標文件,而且指定另一個文件名作為被替換文件的備份,微軟考慮實在周到。

下面是DirectoryInfo類的相關方法:

DirectoryInfo.Create:創建指定目錄,如果指定路徑中有多級目錄不存在,該方法會一一創建;

DirectoryInfo.CreateSubdirectory:創建當前對象對應的目錄的子目錄;

DirectoryInfo.MoveTo:將目錄(及其包含的內容)移動至一個新的目錄,也可用來重命名目錄;

DirectoryInfo.Delete:刪除目錄(如果它存在的話)。如果要刪除一個包含子目錄的目錄,要使用它的重載版本,以指定遞歸刪除。

注意到了沒有?DirectoryInfo類少了一個CopyTo方法,不過我們可以通過遞歸來實現這個功能:

/// <summary>
/// 復制目錄到目標目錄
/// </summary>
/// <param name="source">源目錄</param>
/// <param name="destination">目標目錄</param>
public static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination)
{
// 如果兩個目錄相同,則無須復制
if (destination.FullName.Equals(source.FullName))
{
return;
}
// 如果目標目錄不存在,創建它
if (!destination.Exists)
{
destination.Create();
}
// 復制所有文件
FileInfo[] files = source.GetFiles();
foreach (FileInfo file in files)
{
// 將文件復制到目標目錄
file.CopyTo(Path.Combine(destination.FullName, file.Name), true);
}
// 處理子目錄
DirectoryInfo[] dirs = source.GetDirectories();
foreach (DirectoryInfo dir in dirs)
{
string destinationDir = Path.Combine(destination.FullName, dir.Name);
// 遞歸處理子目錄
CopyDirectory(dir, new DirectoryInfo(destinationDir));
}
}

問題10:如何獲得計算機的所有邏輯驅動器;

解決方案:使用DriveInfo類(需要.NET 2.0)

DriveInfo.GetDrives():獲得計算機的所有邏輯驅動器,返回類型為DriveInfo[];

問題11:如何獲取指定驅動器的信息;

解決方案:

DriveInfo.Name:獲取驅動器的名稱(如C:\);

DriveInfo.DriveType:獲取驅動器的類型(如Fixed,CDRom,Removable,Network等);

DriveInfo.DriveFormat:獲取驅動器的格式(如NTFS,FAT32,CDFS,UDF等);

DriveInfo.IsReady:獲取驅動器是否已准備好,比如CD是否已放入CD驅動器,如果驅動器沒有准備好,訪問其信息會引發IOException類型異常;

DriveInfo.AvailableFreeSpace:獲取驅動器的可用空間;

DriveInfo.TotalFreeSpace:獲取驅動器總的可用空間,它與AvailableFreeSpace的不同在於AvailableFreeSpace會磁盤配額的設置;

DriveInfo.TotalSize:獲取驅動器總的空間;

DriveInfo.RootDirectory:獲得驅動器的根目錄(DirectoryInfo類型);

至此,我們已經了解了文件和目錄相關的一些基本操作。但還不清楚如何去讀寫文件的內容,下一篇中會詳細了解這方面的操作。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved