//C#檔案流寫檔案,預設追加FileMode.Append
string msg = "okffffffffffffffff";
byte[] myByte = System.Text.Encoding.UTF8.GetBytes(msg);
using (FileStream fsWrite = new FileStream(@"D:\1.txt", FileMode.Append))
{
fsWrite.Write(myByte, 0, myByte.Length);
};
//c#檔案流讀檔案
using (FileStream fsRead = new FileStream(@"D:\1.txt", FileMode.Open))
{
int fsLen = (int)fsRead.Length;
byte[] heByte = new byte[fsLen];
int r = fsRead.Read(heByte, 0, heByte.Length);
string myStr = System.Text.Encoding.UTF8.GetString(heByte);
Console.WriteLine(myStr);
Console.ReadKey();
}
FileStream對象表示在磁碟或網路路徑上指向檔案的流。這個類提供了在檔案中讀寫位元組的方法,但經常使用StreamReader或StreamWriter執行這些功能。這是因為FileStream類操作的是位元組和位元組數組,而Stream類操作的是字元資料。字元資料便於使用,但是有些操作,比如隨機檔案訪問(訪問檔案中間某點的資料),就必須由FileStream對象執行,稍後對此進行介紹。
還有幾種方法可以建立FileStream對象。建構函式具有許多不同的重載版本,最簡單的建構函式僅僅帶有兩個參數,即檔案名稱和FileMode枚舉值。
FileStream aFile = new FileStream(filename, FileMode.Member); |
FileMode枚舉有幾個成員,規定了如何開啟或建立檔案。稍後介紹這些枚舉成員。另一個常用的建構函式如下:
FileStream aFile = new FileStream(filename, FileMode.Member, FileAccess. Member); |
第三個參數是FileAccess枚舉的一個成員,它指定了流的作用。FileAccess枚舉的成員如表22-6所示。
表 22-6
成 員 |
說 明 |
Read |
開啟檔案,用於唯讀 |
Write |
開啟檔案,用於唯寫 |
ReadWrite |
開啟檔案,用於讀寫 |
對檔案進行不是FileAccess枚舉成員指定的操作會導致拋出異常。此屬性的作用是,基於使用者的身分識別驗證層級改變使用者對檔案的存取權限。
在FileStream建構函式不使用FileAccess枚舉參數的版本中,使用預設值FileAccess. ReadWrite。
FileMode枚舉成員如表22-7所示。使用每個值會發生什麼,取決於指定的檔案名稱是否表示已有的檔案。注意這個表中的項表示建立流時該流指向檔案中的位置,下一節將詳細討論這個主題。除非特別說明,否則流就指向檔案的開頭。
表 22-7
成 員 |
文 件 存 在 |
檔案不存在 |
Append |
開啟檔案,流指向檔案的末尾,只能與枚舉FileAccess.Write聯合使用 |
建立一個新檔案。只能與枚舉FileAccess.Write聯合使用 |
Create |
刪除該檔案,然後建立新檔案 |
建立新檔案 |
CreateNew |
拋出異常 |
建立新檔案 |
Open |
開啟現有的檔案,流指向檔案的開頭 |
拋出異常 |
OpenOrCreate |
開啟檔案,流指向檔案的開頭 |
建立新檔案 |
Truncate |
開啟現有檔案,清除其內容。流指向檔案的開頭,保留檔案的初始建立日期 |
拋出異常 |
File和FileInfo類都提供了OpenRead()和OpenWrite()方法,更易於建立FileStream對象。前者開啟了唯讀訪問的檔案,後者只允許寫入檔案。這些都提供了捷徑,因此不必以FileStream建構函式的參數形式提供前面所有的資訊。例如,下面的程式碼開啟了用於唯讀訪問的Data.txt檔案:
FileStream aFile = File.OpenRead("Data.txt"); |
注意下面的代碼執行同樣的功能:
FileInfo aFileInfo = new FileInfo("Data.txt");FileStream aFile = aFile.OpenRead(); |
1. 檔案位置
FileStream類維護內部檔案指標,該指標指向檔案中進行下一次讀寫操作的位置。在大多數情況下,當開啟檔案時,它就指向檔案的開始位置,但是此指標可以修改。這允許應用程式在檔案的任何位置讀寫,隨機訪問檔案,或直接跳到檔案的特定位置上。當處理大型檔案時,這非常省時,因為馬上可以定位到正確的位置。
實現此功能的方法是Seek()方法,它有兩個參數:第一個參數規定檔案指標以位元組為單位的移動距離。第二個參數規定開始計算的起始位置,用SeekOrigin枚舉的一個值表示。Seek Origin枚舉包含3個值:Begin、Current和End。
例如,下面的程式碼將檔案指標移動到檔案的第8個位元組,其起始位置就是檔案的第1個位元組:
aFile.Seek(8,SeekOrigin.Begin); |
下面的程式碼將指標從當前位置開始向前移動2個位元組。如果在上面的程式碼之後執行下面的代碼,檔案指標就指向檔案的第10個位元組:
aFile.Seek(2,SeekOrigin.Current); |
注意讀寫檔案時,檔案指標也會改變。在讀取了10個位元組之後,檔案指標就指向被讀取的第10個位元組之後的位元組。
也可以規定負尋找位置,這可以與SeekOrigin.End枚舉值一起使用,尋找靠近檔案末端的位置。下面的代碼會尋找檔案中倒數第5個位元組:
aFile.Seek(–5, SeekOrigin.End); |
以這種方式訪問的檔案有時稱為隨機訪問檔案,因為應用程式可以訪問檔案中的任何位置。稍後介紹的Stream類可以連續地訪問檔案,不允許以這種方式操作檔案指標。
2. 讀取資料
使用FileStream類讀取資料不像使用本章後面介紹的StreamReader類讀取資料那樣容易。這是因為FileStream類只能處理原始位元組(raw byte)。處理原始位元組的功能使FileStream類可以用於任何資料檔案,而不僅僅是文字檔。通過讀取位元組資料,FileStream對象可以用於讀取映像和聲音的檔案。這種靈活性的代價是,不能使用FileStream類將資料直接讀入字串,而使用StreamReader類卻可以這樣處理。但是有幾種轉換類可以很容易地將位元組數群組轉換為字元數組,或者進行相反的操作。
FileStream.Read()方法是從FileStream對象所指向的檔案中訪問資料的主要手段。這個方法從檔案中讀取資料,再把資料寫入一個位元組數組。它有三個參數:第一個參數是傳輸進來的位元組數組,用以接受FileStream對象中的資料。第二個參數是位元組數組中開始寫入資料的位置。它通常是0,表示從數組開端向檔案中寫入資料。最後一個參數指定從檔案中讀出多少位元組。
下面的樣本示範了從隨機訪問檔案中讀取資料。要讀取的檔案實際是為此樣本建立的類檔案。
試試看:從隨機訪問檔案中讀取資料
(1) 在目錄C:\BegVCSharp\Chapter22下建立一個新的控制台應用程式ReadFile。
(2) 在Program.cs檔案的頂部添加下面的using指令:
using System;using System.Collections.Generic;using System.Text;using System.IO; |
(3) 在Main()方