1. 程式人生 > 其它 >最全的C#檔案操作

最全的C#檔案操作

操作某一個檔案/資料夾,需要一個檔案的完整路徑

一、使用File的靜態方法進行檔案操作

//使用file的靜態方法進行復制
File.Copy(path, destpath);
//使用File的靜態方法刪除路徑下的一個檔案
File.Delete(path);
//使用File的靜態方法移動路徑下的一個檔案
File.Move(path, destpath);
File.ReadAllText(path); //開啟一個文字檔案*.txt ,讀取檔案中資料,然後關閉該檔案
//寫入
File.WriteAllText(path, "要寫入檔案的字串"); //建立一個檔案,向其中寫入資料,如果此路徑下有同名檔案則會覆

PS:對檔案進行寫入操作,如果路徑下有同名檔案則會進行覆蓋,所以最好進行一次判斷,跟使用者互動一下在進行覆蓋

二、例項化FileInfo進行操作

FileInfo myfile = new FileInfo(path); //宣告一個物件對某一個檔案進行操作
myfile.CopyTo(destpath);  //對檔案進行復制操作,複製路徑為destpath
myfile.MoveTo(destpath);  //進行移動操作
myfile.Delete();          //進行刪除操作

獲得某一檔案或資料夾的詳細資訊(建立日期,最後一次修改日期等等)

獲取一個檔案,或者資料夾的詳細資訊。(建立日期,檔名等)
            FileInfo myfile 
= new FileInfo(path); //宣告一個物件對某一個檔案進行操作 DateTime dt = myfile.CreationTime; //獲取或設定檔案/資料夾的建立日期 string filepath = myfile.DirectoryName; //僅能用於FileInfo,獲得完整的路徑名,路徑+檔名 bool file = myfile.Exists; //此屬性的值表示檔案或資料夾是否存在,存在會返回True string fullname = myfile.FullName; //
獲取檔案或資料夾的完整路徑名 DateTime lastTime = myfile.LastAccessTime; //獲取或設定最後一次訪問檔案或資料夾的時間 DateTime lastWrite = myfile.LastWriteTime; //獲取或設定最後一次修改資料夾或資料夾的時間 string name = myfile.Name; //獲取檔名,不能修改哦 long length = myfile.Length; //返回檔案的位元組大小 //CreationTime,LastAccessTime,LastWriteTime都是可以被修改的。

如何選擇用哪一個類? File or FileInfo

Directory/File只包含靜態方法,不能被例項化,只需要提供合適的檔案系統物件路徑就可以使用,使用效率較高

當只對檔案或資料夾執行一次操作,使用這些就很有效。

DirectoryInfo/FileInfo 如果使用一個物件執行多個操作,使用這些類就很高效。

因為它們在構造時就讀取了檔案系統物件的身份驗證和其他資訊,無論呼叫了多少方法,都不需要再次讀取這些資訊。

11 檔案操作概述

11.1驅動器

在Windows作業系統中,儲存介質統稱為驅動器,硬碟由於可以劃分為多個區域,每一個區域稱為一個驅動器。.NET Framework提供DriveInfo類和 DriveType列舉型,以方便在程式中直接使用驅動器。DriveInfo類的常用欄位成員有DriveFormat(檔案系統格式,如NTFS或FAT32)、DriveType(驅動器型別)、Name(驅動器名)、TotalSize(總空間)、TotalFreeSpace(獲得驅動器可用空間)。常用的方法成員有GetDrives(獲得可用驅動器列表)。

DriveType列舉型的列舉值有CDRom(光碟機)、Fixed(硬碟)、Network(網路驅動器)和Removeable(軟盤或U盤)等。例如,以下程式碼可以輸出每一個硬碟驅動器的剩餘空間資訊。

DriveInfo[] drivers = DriveInfo.GetDrives();
foreach(DriveInfo driver in drivers)
{
 if(driver.DriveType == DriveType.Fixed && driver.DriveFormat == "NTFS")
 {
 Console.WriteLine("在{0}驅動器上還有{1}位元組的剩餘空間。", driver.Name, driver.AvailableFreeSpace);
 }
}
Console.ReadLine();

11.2目錄

為了方便檢索檔案,需要在驅動器中先建立目錄,然後把檔案儲存到這個目錄中。在Windows作業系統中,目錄又稱資料夾。每個驅動器都有一個根目錄,使用”\”表示,如”C:\”表示C驅動器的根目錄。建立在根目錄中的目錄稱為一級子目錄。在一級子目錄中建立的目錄稱為二級子目錄,依此類推。檔案系統的目錄結構是一種樹形結構。

.NET Framework提供了Directory類和DirectoryInfo類,以方便在程式中直接操作目錄。

Directory類的常用方法成員有CreateDirectory(建立新目錄)、Delete(刪除目錄)、Exists(判斷目錄是否存在)、Move(移動目錄)、GetFiles(獲得目錄的檔案列表)、GetDirectories(獲得子目錄列表)等。

DirectoryInfo類的常用欄位成員有Name(提取目錄名)、Exists(判斷目錄是否存在)、Parent(父目錄)、Root(根目錄)、MoveTo(移動目錄)、GetFiles(獲得目錄的檔案列表)、GetDirectories(獲得子目錄列表)等。例如,以下程式碼分別展現了Directory類和DirectoryInfo類的基本方法。

Directory.CreateDirectory(@"d:\C#程式設計");
if(Directory.Exists(@"d:\C#程式設計"))
{
 Console.WriteLine("建立成功");
}
Directory.Delete(@"d:\C#程式設計");
if (!Directory.Exists(@"d:\C#程式設計"))
{
 Console.WriteLine("刪除成功");
}

DirectoryInfo dir = new DirectoryInfo(@"d:\C#程式設計");
if (!dir.Exists)
{
 dir.Create();
}
else
{
 Console.WriteLine("該目錄已經存在");
}

11.3檔案

.NET Framework提供了File類和FileInfo類,以方便在程式中直接操作檔案。File和FileInfo類位於System.IO名稱空間,都可以用來實現建立、複製、移動、開啟檔案等操作。File類和FileInfo類與Directory類和DirectoryInfo類的工作方式相似。File類是一個靜態類,可直接呼叫其方法成員。FileInfo類不是靜態類,需要先建立例項。

1. 檔案類File

File類的常用方法如表11.1所示。

表11.1 File類的常用方法

常 用 方 法

介 紹

Open()

開啟檔案

Create()

建立檔案

Copy()

複製檔案

Delete()

刪除檔案

Exists()

判斷檔案是否存在

Move()

移動檔案

Replace()

替換檔案

AppendAllText()

新建檔案並新增文字

ReadAllText()

開啟並讀取文字內容

下面通過一個示例演示File類的用法。

(1) 建立一個名為FileCreate的控制檯應用程式專案

(2) 修改Program.cs檔案中的Main方法的內容如下:

//設定所要建立檔案的絕對路徑
string path = @"d:\test.txt";
//以路徑為引數建立檔案
File.Create(path);

程式碼中變數path給出類檔案的路徑,利用File類的Create方法建立類該檔案。檢視D盤根目錄,會有一個新的test.txt的文件出現。

2. 檔案資訊類 FileInfo

檔案資訊類FileInfo與File類不同,它雖然也提供類建立、複製、刪除、移動和開啟檔案的方法,並且幫助建立FileStream物件,但是它提供的僅僅是例項方法。表11.2和表11.3分別展示類FileInfo類的常用欄位和方法。

表 11.2 FileInfo類常用欄位

常用欄位

介紹

Name

提取檔名

Directory

所屬目錄

Exists

是否存在(繼承自父類FileSystemInfo)

Extension

副檔名

Length

檔案長度

IsReadOnly

是否為只讀

表 11.3 FileInfo類常用方法

常用方法

介紹

Open()

開啟檔案

Create()

建立檔案

CopyTo()

複製到新檔案

Delete()

刪除檔案

MoveTo()

移動檔案

Replace()

替換檔案

EnCrypt()

加密檔案

Decrypt()

解密檔案

因此要使用FileInfo類,必須先例項化一個FileInfo物件。FileInfo類的常用方法與File類基本相同。

與檔案類File和資料夾類Directory相比,檔案資訊類FileInfo和資料夾資訊類DirectoryInfo具有其大部分功能。

* File類和Directory類適合對不同的物件進行單一的處理。此種特殊情況下,靜態方法的呼叫速度比較快,不用進行例項化。

* FileInfo類和DirectoryInfo類適合用於對同一檔案或資料夾進行多種操作的情況。此種情況下,例項化後的物件不需要每次都尋找檔案,可以直接對該檔案進行操作。

11.4路徑

每個驅動器包含一個或多個目錄,而每個目錄又可以包含一個或多個子目錄,目錄的結構為樹形結構。一個檔案只能儲存在樹形結構的某個特定的目錄中,檔案所在位置為路徑。要檢索檔案時,必須首先確定檔案的路徑。路徑由驅動器碟符、目錄名、檔名、副檔名和分隔符組成,有兩種種表示方法:一種是從驅動器的根目錄開始書寫,如C:\Windows\System32\notepad.exe,這種路徑稱為絕對路徑;另一種是從當前目錄位置開始書寫,如System32\notepad.exe(假設當前目錄為C:\Windows),這種路徑稱為相對路徑。

在C#中,使用檔案和目錄路徑時要十分謹慎。C#將反斜槓”\”字元視作轉義符,因此當路徑表示為字串時,要使用兩個反斜槓表示,例如:

“C:\\Windows\\System32\\notepad.exe”

另外,C#允許在字串前新增”@”標誌,以提示編譯器不要把”\”字元視作轉義符,而視作普通字元,例如:

@”C:\Windows\System32\notepad.exe”

.NET Framework提供了Path類,以幫助在程式中管理檔案和目錄路徑,Path類位於System.IO名稱空間,是一個靜態類,可以用來操作路徑的每一個欄位,如驅動器碟符、目錄名、檔名、副檔名和分隔符等。Path類的常用欄位成員有PathSeperator(路徑分隔符,如”;”)、DirectorySeparatorChar(目錄分隔符,如”\”)、VolumeSeparator(卷分隔符,如”:”)、AltDirectorySeparator(替換目錄分隔符,如”/”),常用的方法成員有GetDirectoryName(取目錄名)、GetFileName(取檔名)、GetExtension(取副檔名)、GetFullPath(取完整路徑)、GetTempPath(取作業系統的臨時檔案路徑)等,例如,以下程式碼表示提取並顯示路徑中的目錄名和檔名。

string path = @"c:\windows\System32\notepad.exe";
Console.WriteLine(Path.GetDirectoryName(path));
Console.WriteLine(Path.GetFileName(path));

其中,目錄名為”C:\Windows\System32”,檔名為”notepad.exe”。

12 檔案流概述

在.NET Framework中,檔案和流是有區別的。檔案是儲存在磁碟上的資料集,它具有名稱和相應的路徑。當開啟一個檔案並對其進行讀/寫時,該檔案就稱為流(stream)。但是,流不僅僅是指開啟的磁碟檔案,還可以是網路資料。.Net Framework允許在記憶體中建立流。此外,在控制檯應用程式中,鍵盤輸入和文字顯示都是流。流包括以下基本操作:

* 讀取(read):把資料從流傳輸到某種資料結構中,如輸出到字元陣列中。

* 寫入(write):把資料從某種資料結構傳輸到流中,如把位元組陣列中的資料傳輸到流中。

* 定位(seek):在流中查詢或重新定位當前位置。

12.1操作流的類

1. Stream類

Stream類是所有流的抽象基類。Stream類的主要屬性有CanRead(是否支援讀取)、CanSeek(是否支援查詢)、CanTimeout(是否可以超時)、CanWrite(是否支援寫入)、Length(流的長度)、Position(獲取或設定當前流中的位置)、ReadTimeout(獲取或設定讀取操作的超時時間)、WriteTimeout(獲取或設定寫操作的超時時間),主要方法有BeginRead(開始非同步讀操作),BeginWrite(開始非同步寫操作)、Close(關閉當前流)、EndRead(結束非同步讀操作)、EndWrite(結束非同步寫操作)、Flush(清除流的所有緩衝區並把緩衝資料寫入基礎裝置)、Read(讀取位元組序列)、ReadByte(讀取一個位元組)、Seek(設定查詢位置)、Write(寫入位元組序列)、WriteByte(寫入一個位元組)。

2. FileStream、MemoryStream和BufferedStream類

檔案流類FileStream以流的形式讀、寫、開啟、關閉檔案。另外,它還可以用來操作諸如:管道、標準輸入/輸出等其他與檔案相關的作業系統控制代碼。

記憶體流MemoryStream類用來在記憶體中建立流,以暫時保持資料,因此有了它就無須在硬碟上建立臨時檔案。它將資料封裝為無符號的位元組序列,可以直接進行讀、寫、查詢操作。

緩衝流BufferedStream類表示把流先新增到緩衝區,再進行資料的讀/寫操作。緩衝區是儲存區中用來快取資料的位元組塊。使用緩衝區可以減少訪問資料時對作業系統的呼叫次數,增強系統的讀/寫功能。

注意,FileStream類也有緩衝功能,在建立FileStream類的例項時,只需要指定緩衝區的大小即可。

3. StreamReader和StreamWriter類

流讀取器StreamReader類用來以一種特定的編碼(如:UTF-8)從位元組流中讀取字元,流寫入器StreamWriter類用來以一種特定的編碼(如:UTF-8)向流中寫入字元。StreamReader和StreamWriter類一般用來操作文字檔案。

4. BinaryReader和BinaryWriter類

BinaryReader類用特定的編碼將基元資料型別讀作二進位制。BinaryWriter類以二進位制形式將基元型別寫入流,並支援用特定的編碼寫入字串。

12.2檔案流類FileStream

檔案流類FileStream公開了以檔案為主的Stream,既支援同步讀/寫操作,也支援非同步讀/寫操作,FileStream類的特點是操作位元組和位元組陣列。這種方式不適合操作用字元資料構成的文字檔案,適合處理非文字檔案。FileStream類提供了對檔案的低階而複雜的操作,因此能夠實現更多高階的功能。

下面演示FileStreamWriter類的基本用法:

//要寫入檔案的字元陣列
char[] m_cDataWrite = new char[100];
//包含要寫入該流的資料的緩衝區
byte[] m_bDataWrite = new byte[100];

try
{
 //建立d:\file.txt的FileStream物件
 FileStream m_FileStream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate);
 //將要寫入的字串轉換成字元陣列
 m_cDataWrite = "test filestream".ToCharArray();

 //通過UTF-8編碼方法將字元陣列轉成位元組陣列
 Encoder m_Enc = Encoding.UTF8.GetEncoder();
 m_Enc.GetBytes(m_cDataWrite, 0, m_cDataWrite.Length, m_bDataWrite, 0, true);

 //設定流當前位置為檔案開始位置
 m_FileStream.Seek(0, SeekOrigin.Begin);
 //將位元組陣列中的內容寫入檔案
 m_FileStream.Write(m_bDataWrite, 0, m_bDataWrite.Length);
 if (m_FileStream != null)
 {
 //清除此流的緩衝區,使得所有緩衝的資料都寫入到檔案中
 m_FileStream.Flush();
 m_FileStream.Close();
 }
}
catch (Exception ex)
{
 Console.WriteLine("There is an IOException");
 Console.WriteLine(ex.Message);
}
Console.WriteLine("Write to File Succeed!");

程式碼中首先給出了資料夾的路徑,利用Write方法向檔案中寫入部分字串。

下面演示FileStreamReader類的基本用法:

//要寫入檔案的字元陣列
char[] m_cDataWrite = new char[100];
//包含要寫入該流的資料的緩衝區
byte[] m_bDataWrite = new byte[100];

try
{
 //建立d:\file.txt的FileStream物件
 FileStream m_FileStream = new FileStream(@"d:\file.txt", FileMode.Open);

 //設定流當前位置為檔案開始位置
 m_FileStream.Seek(0, SeekOrigin.Begin);
 //將檔案的內容存到位元組陣列中(快取)
 m_FileStream.Read(m_bDataWrite, 0, 100);
}
catch (Exception ex)
{
 Console.WriteLine("There is an IOException");
 Console.WriteLine(ex.Message);
}

//通過UTF-8編碼方法將字元陣列轉換成字元陣列
Decoder m_Dec = Encoding.UTF8.GetDecoder();
m_Dec.GetChars(m_bDataWrite, 0, m_bDataWrite.Length, m_cDataWrite, 0);
Console.WriteLine("Read from file Succeed!");
Console.WriteLine(m_cDataWrite);

程式碼中首先給出了資料夾的路徑,利用Read方法從檔案中讀取了部分字串。

12.3 StreamWriter和StreamReader類

應用FileStream類需要許多額外的資料型別轉換操作,十分影響效率。StreamWriter類允許直接將字元和字串寫入檔案。下面演示其用法:

try
{
 //保留檔案現有資料,以追加寫入的方式開啟d:\file.txt檔案
 StreamWriter m_SW = new StreamWriter(@"d:\file.txt", true);
 //向檔案寫入新字串,並關閉StreamWriter
 m_SW.WriteLine("Another File Operation Method");
 m_SW.Close();
}
catch (Exception ex)
{
 Console.WriteLine("There is an IOException");
 Console.WriteLine(ex.Message);
 }
 StreamWriter類提供了另一種從檔案中讀取資料的方法,下面演示其用法:
try
{
 //以絕對路徑方式構造新的StreamReader物件
 StreamReader m_SR = new StreamReader(@"d:\file.txt");

 //用ReadToEnd方法將d:\file.txt中的資料全部讀入到字串m_Data中,並關閉StreamReader
 string m_Data = m_SR.ReadToEnd();
 m_SR.Close();
 Console.WriteLine(m_Data);
}
catch (Exception ex)
{
 Console.WriteLine("There is an IOException");
 Console.WriteLine(ex.Message);
}

12.4 BinaryReader和BinaryWriter類

BinaryWriter類是除了FileStream和StreamWriter類之外另一種向檔案寫入資料的方式,與之前兩種方式不同,BinaryWriter類將基礎資料(如:字串)以二進位制形式寫入檔案流中,並支援用特定的編碼寫入。下面演示其用法:

FileStream m_FS = new FileStream(@"d:\data.dat", FileMode.Create);
//通過檔案流建立相應的BinaryWriter
BinaryWriter m_BW = new BinaryWriter(m_FS);
for(int i = 0; i < 11; i++)
{
 //向d:\data.dat中寫入資料
 m_BW.Write((int)i);
}

m_BW.Close();
m_FS.Close();

程式碼中首先給出了資料夾的路徑,利用BinaryWriter類的Write方法向檔案中寫入部分二進位制字元。該檔案是以二進位制儲存的,因此用記事本開啟時,將無法觀察到正確的字元,必須使用支援二進位制的文字閱讀器。

BinaryReader類是和BinaryWriter類相對應的二進位制資料讀取類。它用特定的編碼將基元資料型別(如:字串型別)讀作二進位制值。

FileStream m_FS = new FileStream(@"d:\data.dat", FileMode.Open, FileAccess.Read);
//通過檔案流建立相應的BinaryReader
BinaryReader m_BR = new BinaryReader(m_FS);
//從d:\data.dat中讀取資料
for(int i = 0; i < 11; i++)
{
 Console.WriteLine(m_BR.ReadInt32());
}

m_BR.Close();
m_FS.Close();

Console.ReadLine();

程式碼中首先給出了資料夾的路徑。利用BinaryReader類的ReadInt32方法從檔案中讀取了所有的二進位制字元,並將其讀為整數,便於輸出。

13 綜合應用

13.1建立日誌檔案

日誌檔案的作用是記錄程式執行事件。通常使用文字檔案儲存資料。日誌檔案需要程式自動建立,並在指定的事件發生時,使用特定的格式把事件的相關資料記錄到日誌檔案中。

1 技術要點

* 建立FileStream類例項時,能夠通過該類建構函式的引數,指定開啟檔案的方式和讀/寫訪問的方式。通過指定開啟方式,實現日誌檔案的自動建立。

* 使用StreamWriter類例項寫入檔案時,因為部分資料可能由於系統緩慢而未能及時寫入,所以在所有的寫入操作完成後,需要呼叫Flush方法將緩衝區的檔案內容更新到日誌檔案中。

* 使用StreamWriter類例項寫入檔案時,寫入的方式與Console類似,可以使用WriteLine向檔案中寫入一行文字資料。

2 實現程式碼

const string _FILENAME = @"..\..\logfile.txt";
static void Main()
{
 //從指定的目錄以開啟或者建立的形式讀取日誌檔案
 using (FileStream fs = new FileStream(_FILENAME, FileMode.OpenOrCreate, FileAccess.Write))
 {
 //建立日誌檔案的寫入流
 StreamWriter sw = new StreamWriter(fs);
 //向日志文件寫入日誌資訊
 Log("日誌檔案建立成功", sw);
 //關閉日誌檔案寫入流
 sw.Close();
 Console.WriteLine("日誌檔案已建立");
 }

 //讀取並顯示日誌檔案
 using (StreamReader sr = new StreamReader(_FILENAME, Encoding.UTF8))
 {
 string strContent = sr.ReadToEnd();
 sr.Close();
 Console.WriteLine(strContent);
 }

 Console.ReadLine();
}

static void Log(String message, TextWriter tw)
{
 tw.Write("Log Entry:");
 tw.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString());
 tw.WriteLine(" :");
 tw.WriteLine(" :{0}", message);
 tw.WriteLine("----------------------------------");
 //將緩衝區中的內容更新到日誌檔案中
 tw.Flush();
}

3 源程式解讀

(1)程式引用了System.IO名稱空間,在程式頭部應新增對該名稱空間的引用。

(2)程式中定義了表示檔案路徑的常量_FILENAME

(3)在建立FileStream類例項時,使用FileMode.OpenOrCreate模式,即檔案不存在時就建立,存在時就開啟已存在的檔案。

13.2對日誌檔案的讀/寫操作

日誌檔案的讀/寫和文字檔案的讀/寫方法基本相同,日誌檔案除了使用StreamReader類和StreamWriter類的例項進行讀/寫外,還有一些記錄事件的要求。例如,在寫入資料時使用追加的方式、控制日誌檔案的大小等。

1 技術要點

* 使用FileInfo類例項獲取日誌檔案的大小,實現當日志文件的大小超出指定範圍時清空日誌資料的功能。並使用該類例項的OpenWrite方法,建立FileStream類例項進行寫入檔案的操作,實現日誌檔案的自動建立功能。

* 使用StreamWriter類中定義的Seek方法,將寫入位置移動到檔案末尾,實現將資料以追加方式寫入日誌檔案的功能。

* 使用StreamReader類中定義的Peek方法,判斷讀取器是否已經讀到日誌檔案的末尾。

2 實現程式碼

//表示日誌檔案路徑及檔名稱的字串
const string FILENAME = @"..\..\logfile.txt";
static void Main(string[] args)
{
 //寫入日誌資訊
 WriteLogFile(FILENAME, "日誌資訊一");
 //讀取日誌檔案
 Console.WriteLine(ReadLogFile(FILENAME));
 Console.ReadLine();
}

static string ReadLogFile(string FileNameWithPath)
{
 //從指定的目錄以開啟或建立的形式讀取日誌檔案
 FileStream fs = new FileStream(FileNameWithPath, FileMode.OpenOrCreate, FileAccess.Read);
 //定義輸出字串
 StringBuilder output = new StringBuilder();
 //初始化該字串的長度為0
 output.Length = 0;
 //為上面建立的檔案流建立讀取資料流
 StreamReader read = new StreamReader(fs);
 //設定當前流的起始位置為檔案流的起始點
 read.BaseStream.Seek(0, SeekOrigin.Begin);
 //讀取檔案
 while(read.Peek() > -1)
 {
 //取檔案的一行內容並換行
 output.Append(read.ReadLine() + "\n");
 }
 //關閉釋放讀資料流
 read.Close();
 //返回讀到的日誌檔案內容
 return output.ToString();
}

static void WriteLogFile(string FileNameWithPath, string Message)
{
 //定義檔案資訊物件
 FileInfo finfo = new FileInfo(FileNameWithPath);
 //判斷檔案是否存在以及是否大於2K
 if(finfo.Exists && finfo.Length > 2048)
 {
 //刪除該檔案
 finfo.Delete();
 }
 //建立只寫檔案流
 using(FileStream fs = finfo.OpenWrite())
 {
 //根據上面建立的檔案流建立寫資料流
 StreamWriter w = new StreamWriter(fs);
 //設定寫資料流的起始位置為檔案流的末尾
 w.BaseStream.Seek(0, SeekOrigin.End);
 //寫入"Log Entry:"
 w.Write("Log Entry:");
 //寫入系統的當前時間並換行
 w.Write("{0} {1} \r\n", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString());
 //寫入日誌內容並換行
 w.Write(Message + "\r\n");
 //寫入-------------------------並換行
 w.Write("----------------------\r\n");
 //清空緩衝區內容,並把緩衝區內容寫入基礎流
 w.Flush();
 w.Close();
 }

執行結果如下:

Log Entry:14:26:09 2017年5月1日

日誌資訊一

-------------------------------

3 源程式解讀

(1)本示例程式使用寫日誌檔案的WriteLogFile方法向檔案中寫入一條資訊資料,再通過讀取日誌檔案的ReadLogFile方法將日誌檔案的資料顯示出來。本示例程式的流程圖如下所示: 圖1 對日誌檔案讀/寫操作示例程式流程圖

(2)在寫入日誌檔案的WriteLogFile方法中,首先開啟並判斷日誌檔案的大小是否超出了指定的尺寸。如果超出了指定的尺寸,就先將日誌檔案刪除。然後通過FileInfo類例項的OpenWrite方法建立只寫檔案流,向該流中寫入日誌資料。

(3)在讀取日誌檔案的ReadLogFile方法中,首先建立一個StringBuilder類的例項,用來獲取日誌檔案中的文字資料。接著使用StreamReader類定義的BaseStream屬性中的Seek方法,將讀取器位置定位在流的開始位置,然後迴圈讀取日誌檔案中的文字資料,並追加到StringBuilder類例項中,讀取過程中,通過StreamReader類中定義的Peek方法判斷是否讀到檔案末尾。

11.3 複製檔案

靜態File類中提供了許多操作檔案的方法,使用Copy方法複製檔案是比較常見的一種操作,呼叫Copy方法時,可以使用overwrite引數指定是否覆蓋檔案。

1 技術要點

* 使用靜態類File的Exists方法判斷檔案是否存在。

* 使用靜態類File的Copy方法實現複製檔案的功能,當檔案存在時,通過指定override引數覆蓋原有檔案。

* 複製檔案是系統操作,為了保證程式的穩定性,在複製檔案的過程中需要捕獲並處理異常。

2 實現程式碼

//原始檔路徑及檔名
const string SOURCEFILENAME = @"..\..\myfile.txt";
//目標檔案路徑及檔名
const string DESTINATIONFILENAME = @"..\..\result.txt";
static void Main(string[] args)
{
 try
 {
 //判斷原始檔是否存在
 if(!File.Exists(SOURCEFILENAME))
 {
 Console.WriteLine("找不到原始檔");
 }
 else if (File.Exists(DESTINATIONFILENAME))
 {
 Console.Write("目標檔案已經存在,是否覆蓋?(Y/N)");
 if(Console.ReadKey(false).Key == ConsoleKey.Y)
 {
 //覆蓋檔案
 File.Copy(SOURCEFILENAME, DESTINATIONFILENAME, true);
 Console.WriteLine("複製檔案完成");
 }
 else
 {
 Console.WriteLine("取消複製檔案");
 }
 }
 else
 {
 //直接複製
 File.Copy(SOURCEFILENAME, DESTINATIONFILENAME);
 Console.WriteLine("複製檔案完成");
 }
 }
 catch (Exception)
 {
 Console.WriteLine("複製檔案失敗");
 }
 Console.ReadLine();
}

3 源程式解讀

(1)本示例使用File靜態類的方法實現檔案的複製操作。首先判斷原始檔是否存在,如果原始檔不存在,不作任何處理就返回。接著判斷目標檔案是否存在,如果目標檔案不存在,就直接複製檔案,否則就詢問是否覆蓋現有的目標檔案,當用戶選擇覆蓋時,使用原始檔覆蓋目標檔案。

(2)在複製檔案的方法呼叫時,將複製檔案的程式碼放在一個try...catch結構中,以便捕獲並處理複製檔案時出現的異常。

(3)程式執行後,將程式檔案所在目錄下生成一個名為”result.txt”的文字檔案。內容與”myfile.txt”檔案一致。

14小結

本章主要介紹了.NET中的檔案相關的操作。重點介紹了System.IO名稱空間下的File類、Directory類、FileInfo類、DirectoryInfo類及FileStream類、StreamReader類、StreamWriter類、BinaryReader類、BinaryWriter類等。並給出了相應的程式碼示例。

附加:

根據檔案路徑得到記憶體流的方法

        static MemoryStream GetFileStream(string fileName)
        {
            FileStream sr = File.OpenRead(fileName);
            int byteLen = (int)sr.Length;
            byte[] fileBytes = new byte[byteLen];
            int bytesRead = sr.Read(fileBytes, 0, byteLen);
            MemoryStream stream = new MemoryStream(fileBytes);
            sr.Dispose();
            return stream;
        }