檔案操作--文字檔案
1.FileStream 類:
1.1構造
FileStream物件表示在磁碟或網路路徑上指向檔案的流。這個類提供了在檔案中讀寫位元組的方法; 可以隨機檔案訪問(訪問檔案中間某點的資料)。其他Stream類可以讀寫字元資料,但不能隨機訪問檔案;
FileStream aFile = new FileStream(filename, FileMode.Member); FileStream aFile = new FileStream(filename, FileMode.Member, FileAccess. Member); FileStream fs= new FileStream(fileFullName, System.IO.FileMode.Member, System.IO.FileAccess.ReadWrite,FileShare.Member)
FileMode列舉:
成 員 |
文 件 存 在 |
檔案不存在 |
Append |
開啟檔案,流指向檔案的末尾,只能與列舉FileAccess.Write聯合使用 |
建立一個新檔案。只能與列舉FileAccess.Write聯合使用 |
Create |
刪除該檔案,然後建立新檔案 |
建立新檔案 |
CreateNew |
丟擲異常 |
建立新檔案 |
Open |
開啟現有的檔案,流指向檔案的開頭 |
丟擲異常 |
OpenOrCreate |
開啟檔案,流指向檔案的開頭 |
建立新檔案 |
Truncate |
開啟現有檔案,清除其內容。流指向檔案的開頭,保留檔案的初始建立日期 | 丟擲異常 |
FileAccess列舉:指定了對流的作用(寫,讀,讀/寫),如果對檔案進行不是FileAccess指定的操作,就會拋異常。預設值FileAccess.ReadWrite.
成 員 |
說 明 |
Read |
開啟檔案,用於只讀 |
Write |
開啟檔案,用於只寫 |
ReadWrite |
開啟檔案,用於讀寫 |
File和FileInfo類都提供了OpenRead()和OpenWrite()方法,更易於建立FileStream物件。前者打開了只讀訪問的檔案,後者只允許寫入檔案。這些都提供了快捷方式,因此不必以FileStream建構函式的引數形式提供前面所有的資訊。例如,下面的程式碼行打開了用於只讀訪問的Data.txt檔案:
FileStream aFile = File.OpenRead("Data.txt");
注意下面的程式碼執行同樣的功能:
FileInfo aFileInfo = new FileInfo("Data.txt"); FileStream aFile = aFile.OpenRead();
FileShare列舉:控制其他FileStream 物件對同一檔案的共享操作。列舉在對檔案在操作過程中,檔案同時被其他物件的訪問許可權許可權。
成 員 |
說 明 |
Read |
檔案正本一個程序操作,則其他流物件只能讀檔案 |
Write |
檔案正本一個程序操作,則其他流物件可以寫檔案 |
ReadWrite |
檔案正本一個程序操作,則其他流物件可以讀、寫檔案 |
None |
獨佔訪問,包括讀寫。 |
1.2.檔案定位
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類可以連續地訪問檔案,不允許以這種方式操作檔案指標。
1.3.讀取資料
使用FileStream類讀取資料不像使用本章後面介紹的StreamReader類讀取資料那樣容易。這是因為FileStream類只能處理原始位元組(raw byte)。處理原始位元組的功能使FileStream類可以用於任何資料檔案,而不僅僅是文字檔案。通過讀取位元組資料,FileStream物件可以用於讀取影象和聲音的檔案。這種靈活性的代價是,不能使用FileStream類將資料直接讀入字串,而使用StreamReader類卻可以這樣處理。但是有幾種轉換類可以很容易地將位元組陣列轉換為字元陣列,或者進行相反的操作。
FileStream.Read()方法是從FileStream物件所指向的檔案中訪問資料的主要手段。這個方法從檔案中讀取資料,再把資料寫入一個位元組陣列。它有三個引數:第一個引數是傳輸進來的位元組陣列,用以接受FileStream物件中的資料。第二個引數是位元組陣列中開始寫入資料的位置。它通常是0,表示從陣列開端向檔案中寫入資料。最後一個引數指定從檔案中讀出多少位元組。
byte[] byData = new byte[200]; char[] charData = new Char[200]; try { FileStream aFile = new FileStream("http://www.cnblogs.com/Program.cs",FileMode.Open); aFile.Seek(135,SeekOrigin.Begin); aFile.Read(byData,0,200); } catch(IOException e) { Console.WriteLine("An IO exception has been thrown!"); Console.WriteLine(e.ToString()); Console.ReadKey(); return; } Decoder d = Encoding.UTF8.GetDecoder(); d.GetChars(byData, 0, byData.Length, charData, 0); Console.WriteLine(charData); Console.ReadKey();
檔案IO涉及到的所有操作都可以丟擲型別為IOException的異常。所有產品程式碼都必須包含錯誤處理,尤其是處理檔案系統時更是如此。
從檔案中獲取了位元組陣列後,就需要將其轉換為字元陣列,以便在控制檯顯示它。為此,使用System.Text名稱空間的Decoder類。此類用於將原始位元組轉換為更有用的項,比如字元:
Decoder d = Encoding.UTF8.GetDecoder(); d.GetChars(byData, 0, byData.Length, charData, 0); |
這些程式碼基於UTF8編碼模式建立了Decoder物件。這就是Unicode編碼模式。然後呼叫GetChars()方法,此方法提取位元組陣列,將它轉換為字元陣列。完成之後,就可以將字元陣列輸出到控制檯。
1.4. 寫入資料
byte[] byData; char[] charData; try { FileStream aFile = new FileStream("Temp.txt", FileMode.Create); charData = "My pink half of the drainpipe.".ToCharArray(); byData = new byte[charData.Length]; Encoder e = Encoding.UTF8.GetEncoder(); e.GetBytes(charData, 0, charData.Length, byData, 0, true); // Move file pointer to beginning of file. aFile.Seek(0, SeekOrigin.Begin); aFile.Write(byData, 0, byData.Length); } catch (IOException ex) { Console.WriteLine("An IO exception has been thrown!"); Console.WriteLine(ex.ToString()); Console.ReadKey(); return; }
此應用程式在自己的目錄中開啟檔案,並在檔案中寫入了一個簡單的字串。在結構上這個示例非常類似於前面的示例,只是用Write()代替了Read(),用Encoder代替了Decoder。
這次,要基於UTF8編碼方法來建立Encoder物件。也可以將Unicode用於解碼。這裡在寫入流之前,需要將字元資料編碼為正確的位元組格式。在GetBytes()方法中可以完成這些工作,它可以將字元陣列轉換為位元組陣列,並將字元陣列作為第一個引數(本例中的charData),將該陣列中起始位置的下標作為第二個引數(0表示陣列的開頭)。第三個引數是要轉換的字元數量(charData.Length,charData陣列中的元素個數)。第四個引數是在其中置入資料的位元組陣列(byData),第五個引數是在位元組陣列中開始寫入位置的下標(0表示byData陣列的開頭)。
最後一個引數決定在結束後Encoder物件是否應該更新其狀態,即Encoder物件是否仍然保留它原來在位元組陣列中的記憶體位置。這有助於以後呼叫Encoder物件,但是當只進行單一呼叫時,這就沒有什麼意義。最後對Encoder的呼叫必須將此引數設定為true,以清空其記憶體,釋放物件,用於垃圾回收。
之後,使用Write()方法向FileStream寫入位元組陣列就非常簡單:
aFile.Seek(0,SeekOrigin.Begin); aFile.Write(byData,0,byData.Length); |
與Read()方法一樣,Write()方法也有三個引數:要寫入的陣列,開始寫入的陣列下標和要寫入的位元組數。
2.StreamReader 類:從流中讀取字元
3.StreamWriter類:它是按照一種特定的編碼從位元組流中寫入字元,
3.1構造:
public StreamWriter(Stream stream, Encoding encoding); // // 摘要: // 使用預設編碼和緩衝區大小,為指定路徑上的指定檔案初始化 System.IO.StreamWriter 類的新例項。如果該檔案存在,則可以將其覆蓋或向其追加。如果該檔案不存在,則此建構函式將建立一個新檔案。 // // 引數: // path: // 要寫入的完整檔案路徑。 // // append: // 確定是否將資料追加到檔案。如果該檔案存在,並且 append 為 false,則該檔案被覆蓋。如果該檔案存在,並且 append 為 true,則資料被追加到該檔案中。否則,將建立新檔案。 // // 異常: // System.UnauthorizedAccessException: // 訪問被拒絕。 // // System.ArgumentException: // path 為空。- 或 -path 包含系統裝置的名稱(com1、com2 等等)。 // // System.ArgumentNullException: // path 為 null。 // // System.IO.DirectoryNotFoundException: // 指定的路徑無效,比如在未對映的驅動器上。 // // System.IO.IOException: // path 包含不正確或無效的檔名、目錄名或卷標的語法。 // // System.IO.PathTooLongException: // 指定的路徑、檔名或者兩者都超出了系統定義的最大長度。例如,在基於 Windows 的平臺上,路徑必須小於 248 個字元,檔名必須小於 260 // 個字元。 // // System.Security.SecurityException: // 呼叫方沒有所要求的許可權。 [SecuritySafeCritical] public StreamWriter(string path, bool append); // // 摘要: // 用指定的編碼及緩衝區大小,為指定的流初始化 System.IO.StreamWriter 類的新例項。 // // 引數: // stream: // 要寫入的流。 // // encoding: // 要使用的字元編碼。 // // bufferSize: // 設定緩衝區大小。 // // 異常: // System.ArgumentNullException: // stream 或 encoding 為 null。 // // System.ArgumentOutOfRangeException: // bufferSize 為負。 // // System.ArgumentException: // stream 不可寫。 [SecuritySafeCritical] public StreamWriter(Stream stream, Encoding encoding, int bufferSize); // // 摘要: // 使用指定編碼和預設緩衝區大小,為指定路徑上的指定檔案初始化 System.IO.StreamWriter 類的新例項。如果該檔案存在,則可以將其覆蓋或向其追加。如果該檔案不存在,則此建構函式將建立一個新檔案。 // // 引數: // path: // 要寫入的完整檔案路徑。 // // append: // 確定是否將資料追加到檔案。如果該檔案存在,並且 append 為 false,則該檔案被覆蓋。如果該檔案存在,並且 append 為 true,則資料被追加到該檔案中。否則,將建立新檔案。 // // encoding: // 要使用的字元編碼。 // // 異常: // System.UnauthorizedAccessException: // 訪問被拒絕。 // // System.ArgumentException: // path 為空。- 或 -path 包含系統裝置的名稱(com1、com2 等等)。 // // System.ArgumentNullException: // path 為 null。 // // System.IO.DirectoryNotFoundException: // 指定的路徑無效,比如在未對映的驅動器上。 // // System.IO.IOException: // path 包含不正確或無效的檔名、目錄名或卷標的語法。 // // System.IO.PathTooLongException: // 指定的路徑、檔名或者兩者都超出了系統定義的最大長度。例如,在基於 Windows 的平臺上,路徑必須小於 248 個字元,檔名必須小於 260 // 個字元。 // // System.Security.SecurityException: // 呼叫方沒有所要求的許可權。 [SecuritySafeCritical] public StreamWriter(string path, bool append, Encoding encoding); // // 摘要: // 使用指定編碼和緩衝區大小,為指定路徑上的指定檔案初始化 System.IO.StreamWriter 類的新例項。如果該檔案存在,則可以將其覆蓋或向其追加。如果該檔案不存在,則此建構函式將建立一個新檔案。 // // 引數: // path: // 要寫入的完整檔案路徑。 // // append: // 確定是否將資料追加到檔案。如果該檔案存在,並且 append 為 false,則該檔案被覆蓋。如果該檔案存在,並且 append 為 true,則資料被追加到該檔案中。否則,將建立新檔案。 // // encoding: // 要使用的字元編碼。 // // bufferSize: // 設定緩衝區大小。 // // 異常: // System.ArgumentException: // path 為空字串 ("")。- 或 -path 包含系統裝置的名稱(com1、com2 等等)。 // // System.ArgumentNullException: // path 或 encoding 為 null。 // // System.ArgumentOutOfRangeException: // bufferSize 為負。 // // System.IO.IOException: // path 包含不正確或無效的檔名、目錄名或卷標的語法。 // // System.Security.SecurityException: // 呼叫方沒有所要求的許可權。 // // System.UnauthorizedAccessException: // 訪問被拒絕。 // // System.IO.DirectoryNotFoundException: // 指定的路徑無效,比如在未對映的驅動器上。 // // System.IO.PathTooLongException: // 指定的路徑、檔名或者兩者都超出了系統定義的最大長度。例如,在基於 Windows 的平臺上,路徑必須小於 248 個字元,檔名必須小於 260 // 個字元。 [SecuritySafeCritical] public StreamWriter(string path, bool append, Encoding encoding, int bufferSize);
3.2 Write() 和WriteLine()
try { using (StreamWriter sw= new StreamWriter("TestFile.txt")) { string str1 = "abc"; string str2 = "def"; sw.WriteLine(str1); sw.Write(str2); } } catch (Exception e) { Console.WriteLine("The file could not be read:"); Console.WriteLine(e.Message); }
StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default);
來自參考:https://www.cnblogs.com/Fskjb/archive/2010/03/12/1684753.html