C# 基礎知識系列- 14 IO篇 檔案的操作
@
目錄
- 前言
-
檔案、目錄和路徑
1.1 File和FileInfo
1.1.1 File工具類
1.1.2 FileInfo 對象類
1.2 Directory和DirectoryInfo
1.2.1 Directory
1.2.2 DirectoryInfo
- 本章節是IO篇的第二集,我們在上一篇中介紹了C#中IO的基本概念和一些基本方法,接下來我們介紹一下操作檔案的方法。在程式設計的世界中,操作檔案是一個很重要的技能。
- 在開始操作之前,先大概講解一下基本概念。在計算機系統中,檔案是以硬碟為載體存儲在計算機上的資訊集合。檔案通常會有一個字尾名,表示檔案格式(當然,通常的另一個含義就是可能沒有)。我們最常見到的圖檔檔案,字尾有jpg/png/gif這些常見的;文本檔案為txt等。
目錄,不嚴謹的來講可以用檔案夾代替。不過嚴格來說,目錄指的是檔案所在的檔案夾以及檔案夾的位置這些資訊的集合。
路徑是指檔案或檔案夾所在的位置的字元串表示,有相對路徑和絕對路徑,有實體路徑和網絡路徑等一系列這些劃分。
相對路徑指的是,相對程式所在目錄目标檔案所在的目錄路徑
絕對路徑指的是從系統或者網站的目錄起點開始檔案所在的位置,也就是說無論程式在哪都能通過絕對路徑通路到對應檔案
實體路徑是指檔案在磁盤的路徑,劃分依據與之前的兩種并不一緻,是以不是并列關系
網絡路徑是指網絡或檔案是在網絡服務上部署的,通過URI通路的路徑資訊
好了,基本概念介紹到這裡,讓我們來看看如何實作C#操作檔案吧。
C# 提供了兩個通路檔案的入口,File和FileInfo這兩個類。有人可能要迷惑了,為啥要提供兩個呢,這兩個又有啥子不一樣的呢?别急,讓我們來一起看一看吧。
我們先來觀察一下兩個類的聲明方式有什麼不一樣的:
public static class File;
public sealed class FileInfo : System.IO.FileSystemInfo;
我們忽略突然冒出來的FileSystemInfo,隻需要明白它是FileInfo的基類即可。
通過兩個類的聲明方式,可以看出File是一個工具類,而FileInfo則是檔案對象。是以,File更多的用在快速操作檔案并不需要長時間多次使用同一個檔案的場景,而FileInfo則适合同一個檔案的多次使用。
我們先來看下File支援哪些操作:
a.檔案讀取
public static byte[] ReadAllBytes (string path);
public static string[] ReadAllLines (string path);
public static string[] ReadAllLines (string path, System.Text.Encoding encoding);
public static string ReadAllText (string path);
public static string ReadAllText (string path, System.Text.Encoding encoding);
public static System.Collections.Generic.IEnumerable ReadLines (string path);
先從名稱上分析方法應該是什麼,應該具有哪些功能?
ReadAllBytes以二進制的形式一次性把檔案全部讀出來
ReadAllLines打開文本檔案,将檔案内容一行一行的全部讀出來并傳回
ReadAllText打開檔案,并将檔案所有内容一次性讀出來
ReadLines 這是一個新的方法,根據傳回值和方法名稱,可以判斷它應該與ReadAllLines有着類似的行為
ReadLInes和ReadAllLines的差別:
ReadAllLines傳回的是字元串數組,是以該方法會一次性将檔案内容全部讀出
ReadLines傳回的是一個可枚舉對象,根據之前在Linq系列和集合系列的知識,我們能判斷出,這個方法不會立即傳回資料
是以我們很輕易的就能得出,ReadAllLines不會過久的持有檔案對象,但是不适合操作大檔案;ReadLines對于大檔案的操作更擅長一些,但是可能會更久的持有檔案
b.寫入檔案
public static void AppendAllLines (string path, System.Collections.Generic.IEnumerable contents);
public static void AppendAllLines (string path, System.Collections.Generic.IEnumerable contents, System.Text.Encoding encoding);
public static void AppendAllText (string path, string contents);
public static void AppendAllText (string path, string contents, System.Text.Encoding encoding);
public static void WriteAllBytes (string path, byte[] bytes);
public static void WriteAllLines (string path, string[] contents, System.Text.Encoding encoding);
public static void WriteAllText (string path, string contents);
public static void WriteAllText (string path, string contents, System.Text.Encoding encoding);
來,我們簡單看一下這幾個方法具體作用:
AppendAllLines:追加行到檔案末尾
AppendAllText :将字元串内容追加到檔案末尾
WriteBytes:将位元組數組寫到檔案裡,如果檔案有内容就覆寫原有内容
WriteAllLines:按行寫入檔案中,如果檔案有内容則覆寫原有内容
WriteAllText:将内容寫入檔案,如果檔案有内容則覆寫原有内容
在使用File寫入檔案的時候,如果檔案不存在則會自動建立檔案。
- 複制檔案
File類提供了簡單易用的複制檔案功能,隻需要指定源檔案和新檔案即可:
public static void Copy (string sourceFileName, string destFileName);
public static void Copy (string sourceFileName, string destFileName, bool overwrite);
這兩個方法對的作用就是将 sourceFileName複制為destFileName。第一個方法不允許複制為已存在的檔案,也就是說如果destFileName已存在則報錯。第二個方法則通過overwrite指定是否覆寫。
d.移動檔案
與複制檔案相同的使用方式,File提供了移動檔案的方法:
public static void Move (string sourceFileName, string destFileName);
public static void Move (string sourceFileName, string destFileName, bool overwrite);
注意事項與複制檔案一緻。
e.删除檔案
public static void Delete (string path);
FileInfo提供了檔案的建立、複制、删除、移動和打開等屬性和執行個體方法。我們先來看看,如果建立一個FileInfo:
public FileInfo (string fileName);
通過指定檔案路徑,來換取一個FileInfo對象,如果fileName指定的是目錄則會提示錯誤。
好,現在我們已經可以擷取一個FileInfo對象執行個體了,那麼一起來看看FileInfo支援哪些内容吧:
- 先來看看檔案的基本屬性
public override bool Exists { get; }
檔案是否存在,等效于File.Existss(string path)。
public string DirectoryName { get; }
擷取檔案所在目錄的完整路徑(絕對路徑)。
public System.IO.DirectoryInfo Directory { get; }
擷取檔案所在目錄的目錄類型執行個體。
public long Length { get; }
擷取檔案的大小,機關是位元組。
public override string Name { get; }
擷取檔案名,包括檔案的擴充名。
- 檔案的操作
對于FileInfo執行個體來說,對于檔案的操作大多都是基于流來完成的(這部分請留意下一篇内容),這裡先看一下它的執行個體方法:
public System.IO.StreamWriter AppendText ();//建立一個流擴充卡,在擴充卡裡追加文本到檔案中
public System.IO.FileInfo CopyTo (string destFileName);//将現有檔案複制到新檔案,并傳回新檔案的執行個體,不支援覆寫
public System.IO.FileInfo CopyTo (string destFileName, bool overwrite);//根據orverwrite确定是否覆寫
public System.IO.FileStream Create ();//建立目前對象代表的檔案,并傳回一個檔案流
public System.IO.StreamWriter CreateText ();//與AppendText類似,但會覆寫檔案原有内容
public override void Delete ();//删除檔案
public void MoveTo (string destFileName);// 将檔案移動到新檔案,不支援覆寫已存在檔案
public void MoveTo (string destFileName, bool overwrite);// 根據overwrite确定是否覆寫
public System.IO.FileStream Open (System.IO.FileMode mode);// 根據模式打開檔案
public System.IO.FileStream Open (System.IO.FileMode mode, System.IO.FileAccess access);//指定權限和模式,打開檔案
public System.IO.FileStream OpenRead ();//打開一個隻能讀取的檔案流
public System.IO.StreamReader OpenText ();//打開一個讀流擴充卡
public System.IO.FileStream OpenWrite ();// 打開一個隻能寫的流
最新版C#的API,取消了通過FileInfo擷取檔案的格式名的屬性以及其他的很多屬性,隻保留了文中提到的幾個屬性。
與之前的類似,Directory也是個工具類,DirectoryInfo則代表目錄執行個體。
先來個簡單的:
- 建立目錄:
public static System.IO.DirectoryInfo CreateDirectory (string path);
如果目錄已存在,則跳過建立,直接傳回指定路徑的DirectoryInfo執行個體
b.是否存在:
public static bool Exists (string path);
傳回是否存在這個目錄。
c.傳回目錄下的所有檔案
public static string[] GetFiles (string path);
- 傳回目錄下的所有子目錄:
public static string[] GetDirectories (string path);
public static string[] GetDirectories (string path, string searchPattern);
public static string[] GetDirectories (string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions);
public static string[] GetDirectories (string path, string searchPattern, System.IO.SearchOption searchOption);
除了上文提到的 GetDirectories 方法可以直接傳回目錄下所有子目錄以外,還有一組方法也可以枚舉出目前目錄下的子目錄:
public static System.Collections.Generic.IEnumerable EnumerateDirectories (string path);
枚舉 path 目錄下的所有子目錄。
public static System.Collections.Generic.IEnumerable EnumerateDirectories (string path, string searchPattern);
searchPattern,搜尋名稱字元串,可以包含有效文本路徑和通配符(* 和 ?)的組合,但不支援正規表達式。
public static System.Collections.Generic.IEnumerable EnumerateDirectories (string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions);
public static System.Collections.Generic.IEnumerable EnumerateDirectories (string path, string searchPattern, System.IO.SearchOption searchOption);
這兩個方法放在一起講,這兩個是對上一個方法的增強和補充。其中 EnumerationOptions 是類,可以配置查詢的條件;SearchOption 是個枚舉,選擇隻查詢目前目錄的子目錄名稱還是繼續深入查詢子孫目錄。
e.檢視目錄下的所有檔案-補充
與子目錄查詢相同,Directory也支援這麼幾組查詢方法:
public static string[] GetFiles (string path, string searchPattern);
public static string[] GetFiles (string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions);
public static string[] GetFiles (string path, string searchPattern, System.IO.SearchOption searchOption);
從參數上看,可以看出來這是傳回子目錄下的檔案清單。其中使用 searchPattern查詢名稱,enumerationOptions 作為查詢條件,searchOption 作為查詢的深度。
同樣,查詢檔案也可以使用枚舉方法:
public static System.Collections.Generic.IEnumerable EnumerateFiles (string path);
public static System.Collections.Generic.IEnumerable EnumerateFiles (string path, string searchPattern);
public static System.Collections.Generic.IEnumerable EnumerateFiles (string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions);
public static System.Collections.Generic.IEnumerable EnumerateFiles (string path, string searchPattern, System.IO.SearchOption searchOption);
f.擷取目前目錄
public static string GetCurrentDirectory ();
在程式中調用這個方法可以擷取程式執行時的目錄,如果是在調試階段,目錄是指程式的主方法所在目錄;如果在釋出之後,也就是運作階段,該目錄指程式所在目錄。
g.擷取上級目錄
public static System.IO.DirectoryInfo GetParent (string path);
擷取傳入目錄的上級目錄資訊。
h.目錄移動
public static void Move (string sourceDirName, string destDirName);
sourceDirName 移動到 destDirName,其中destDirName所代表的目錄不能純在。這個方法有個很有意思的特點,它也支援移動檔案。也就是說,如果sourceDirNanme指向的是一個檔案,那麼destDirName也必須是一個檔案類型的路徑字元串。
i.删除目錄
public static void Delete (string path);//删除 path所代表的目錄,如果目錄非空則提示無法删除
public static void Delete (string path, bool recursive);// recursive訓示是否同時删除子目錄和檔案
以上是Directory類的一些常用方法,當然還有更多的内容留待小夥伴一起發掘。傳送門==>
https://docs.microsoft.com/zh-cn/dotnet/api/system.io.directory?view=netcore-3.1之前的篇幅我們介紹了Directory的工具類所支援的方法,接下來我們看一下 DirectoryInfo有哪些屬性和方法吧。
public DirectoryInfo (string path);
初始化的方式很簡單,直接傳遞一個目錄的路徑字元串,就可以擷取一個目錄資訊類了。
接下來看看,DirectoryInfo支援的屬性:
public override bool Exists { get; }// 目錄是否存在
public override string Name { get; }// 目錄名稱,不是路徑
public System.IO.DirectoryInfo Parent { get; }//如果有上級目錄,則傳回上級目錄,如果沒有則傳回 null
public System.IO.DirectoryInfo Root { get; }//擷取目錄的根目錄
我們路過了DirectoryInfo的屬性,看到了它一部分特點,那麼我們該怎麼使用呢?
public void Create ();
建立目錄資訊所代表的目錄,如果目錄已存在,則不會有任何變化 。如果這個目錄的父目錄也不存在,則自動建立父目錄
public System.IO.DirectoryInfo CreateSubdirectory (string path);
建立 pathi指定的子目錄。
public override void Delete ();
如果目前目錄是空目錄,調用可直接删除,如果非空則會提示錯誤。
public void Delete (bool recursive);
根據參數 recursive指定是否删除目前目錄的子目錄。
public System.IO.DirectoryInfo[] GetDirectories ();
public System.IO.DirectoryInfo[] GetDirectories (string searchPattern);
public System.IO.DirectoryInfo[] GetDirectories (string searchPattern, System.IO.EnumerationOptions enumerationOptions);
public System.IO.DirectoryInfo[] GetDirectories (string searchPattern, System.IO.SearchOption searchOption);
擷取子目錄的數組,參數與 Directory 的同名方法一緻。
public System.Collections.Generic.IEnumerable EnumerateDirectories ();
public System.Collections.Generic.IEnumerable EnumerateDirectories (string searchPattern);
public System.Collections.Generic.IEnumerable EnumerateDirectories (string searchPattern, System.IO.EnumerationOptions enumerationOptions);
public System.Collections.Generic.IEnumerable EnumerateDirectories (string searchPattern, System.IO.SearchOption searchOption);
傳回一個子目錄資訊的可枚舉集合。
public System.IO.FileInfo[] GetFiles ();
public System.IO.FileInfo[] GetFiles (string searchPattern);
public System.IO.FileInfo[] GetFiles (string searchPattern, System.IO.EnumerationOptions enumerationOptions);
public System.IO.FileInfo[] GetFiles (string searchPattern, System.IO.SearchOption searchOption);
嗯,依舊類似的寫法,擷取檔案資訊的數組
public System.Collections.Generic.IEnumerable EnumerateFiles ();
public System.Collections.Generic.IEnumerable EnumerateFiles (string searchPattern);
public System.Collections.Generic.IEnumerable EnumerateFiles (string searchPattern, System.IO.EnumerationOptions enumerationOptions);
public System.Collections.Generic.IEnumerable EnumerateFiles (string searchPattern, System.IO.SearchOption searchOption);
傳回檔案的可枚舉集合。
public void MoveTo (string destDirName);
把目前目錄移動到對應的目錄。
依舊未完待續,下一篇将為大家介紹一下 Path類和FileInfo與DirectoryInfo的父類 FileSystemInfo 這兩個類的API,然後示範一下如何使用流來讀寫檔案。在檔案和目錄這塊内容裡,我故意忽略了權限的介紹,這部分我将會放在進階篇中介紹。
API的介紹總是這麼枯燥乏味,不過請期待一下,在IO篇完成後,我會示範一下如何做一個簡單的檔案查找工具。
簡單介紹一下這個工具的内容:它會周遊系統裡所有檔案的路徑資訊,然後記錄到一個緩存檔案中,使用者輸入一個要查詢的檔案名時,我們可以通過讀取緩存檔案确認檔案所在目錄。
原文位址
https://www.cnblogs.com/c7jie/p/12812830.html