.NET Core C# 中級篇2-7 檔案操作

WarrenRyan發表於2019-08-28

.NET Core CSharp 中級篇2-7

本節內容為檔案操作

簡介

檔案操作在我們C#裡還是比較常見的,例如我們讀取Excel、Txt檔案的內容,在程式中,這些檔案都是以流的方式讀取進入我們記憶體中,本節內容會詳細的講解有關檔案的操作的方法。

我們從最大的驅動器開始往檔案這個最小的開始講解

驅動器讀取

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

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

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();

目錄

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

.NET提供了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("該目錄已經存在");
}

檔案

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

File類

File類是一個檔案的基本操作類,提供用於建立、複製、刪除、移動和開啟檔案的靜態方法,並協助建立 FileStream 物件。裡面包含的大多都是實際操作檔案的方法,我用一個列表表示它內部常用的方法

  • Open(string path, FileMode mode)+3過載 開啟指定路徑檔案
  • Create(string path)+3過載,在指定路徑建立檔案,可以指定緩衝區大小
  • Copy(string sourceFileName, string destFileName),複製檔案
  • Delete(string path),刪除檔案
  • Exists(),判斷檔案是否存在
  • Move(string sourceFileName, string destFileName),移動檔案
  • Replace(string sourceFileName,string destinationFileName,
    string destinationBackupFileName),替換檔案
  • AppendAllText(string path, string contents)新建檔案並新增文字
  • ReadAllText(string path, Encoding encoding)+2過載,開啟並讀取文字內容(可以指定開啟的編碼格式)

這些方法的使用也是非常簡單,例如:

string path = @"E:\test.txt";
//以路徑為引數建立檔案
File.Create(path);

更多的使用你最好自己去嘗試,我們這幾節的內容都是一些常用的類和方法的實際運用,並沒有過多的知識點,你只需要按著這裡的操作一直嘗試即可。

FileInfo類

FileInfo類也可以對檔案進行操作,檔案資訊類FileInfo與File類不同,它雖然也提供類建立、複製、刪除、移動和開啟檔案的方法,並且幫助建立FileStream物件,但是它提供的僅僅是例項方法他是我們最常用的檔案操作類。

它裡面含有的屬性有:

  • Name 提取檔名
  • Directory 所屬目錄
  • Exists 是否存在(繼承自父類FileSystemInfo)
  • Extension 副檔名
  • Length 檔案長度
  • IsReadOnly 是否為只讀

常用的方法和File類類似,這裡新增幾個之前沒有講過的

  • EnCrypt() 加密檔案
  • Decrypt() 解密檔案
  • CopyTo() 複製到新檔案
  • MoveTo() 移動檔案

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

  • File類和Directory類適合對不同的物件進行單一的處理。此種特殊情況下,靜態方法的呼叫速度比較快,不用進行例項化。
  • FileInfo類和DirectoryInfo類適合用於對同一檔案或資料夾進行多種操作的情況。此種情況下,例項化後的物件不需要每次都尋找檔案,可以直接對該檔案進行操作。

檔案流

檔案流對我們而言是一個陌生的概念,事實上,你仔細思考一下,我們是如何透過File類和FileInfo類讀取檔案中的內容呢?它其實就是以檔案流的形式進行讀寫。流包括以下基本操作:

  • 讀取(read):把資料從流傳輸到某種資料結構中,如輸出到字元陣列中。
  • 寫入(write):把資料從某種資料結構傳輸到流中,如把位元組陣列中的資料傳輸到流中。
  • 定位(seek):在流中查詢或重新定位當前位置。

在C#中,所有的流操作都繼承於Stream類,Stream類的主要屬性有

  • CanRead(是否支援讀取)
  • CanSeek(是否支援查詢)
  • CanTimeout(是否可以超時)
  • CanWrite(是否支援寫入)
  • Length(流的長度)
  • Position(獲取或設定當前流中的位置)
  • ReadTimeout(獲取或設定讀取操作的超時時間)
  • WriteTimeout(獲取或設定寫操作的超時時間)

主要方法有

  • BeginRead(開始非同步讀操作)
  • BeginWrite(開始非同步寫操作)
  • Close(關閉當前流)
  • EndRead(結束非同步讀操作)
  • EndWrite(結束非同步寫操作)
  • Flush(清除流的所有緩衝區並把緩衝資料寫入基礎裝置)
  • Read(讀取位元組序列)
  • ReadByte(讀取一個位元組)
  • Seek(設定查詢位置)
  • Write(寫入位元組序列)
  • WriteByte(寫入一個位元組)。

FileStream、MemoryStream和BufferedStream類

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

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

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

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

示例

//要寫入檔案的字元陣列
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!");

StreamReader和StreamWriter類

流讀取器StreamReader類用來以一種特定的編碼(如:UTF-8)從位元組流中讀取字元,流寫入器StreamWriter類用來以一種特定的編碼(如:UTF-8)向流中寫入字元。StreamReader和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);
}

BinaryReader和BinaryWriter類

BinaryReader類用特定的編碼將基後設資料型別讀作二進位制。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();


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();

Reference

《c# 程式設計兵書》第11章 張志強 胡君 編著

如果我的文章幫助了您,請您在github.NETCoreGuide專案幫我點一個star,在部落格園中點一個關注和推薦。

Github

BiliBili主頁

WarrenRyan'sBlog

部落格園

相關文章