C# FileStream文件讀寫詳解。本站提示廣大學習愛好者:(C# FileStream文件讀寫詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是C# FileStream文件讀寫詳解正文
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
對文件停止不是FileAccess列舉成員指定的操作會招致拋出異常。此屬性的感化是,基於用戶的身份驗證級別轉變用戶對文件的拜訪權限。
在FileStream結構函數不應用FileAccess列舉參數的版本中,應用默許值FileAccess. ReadWrite。
FileMode列舉成員如表22-7所示。應用每一個值會產生甚麼,取決於指定的文件名能否表現已有的文件。留意這個表中的項表現創立流時該流指向文件中的地位,下一節將具體評論辯論這個主題。除非特殊解釋,不然流就指向文件的開首。
表 22-7
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()辦法中添加上面的代碼:
static void Main(string[] args)
{
byte[] byData = new byte[200];
char[] charData = new Char[200];
try
{
FileStream aFile = new FileStream("E:\\Workplace\\TestSolution\\Test.ConsoleApplication\\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();
}
(4) 運轉運用法式。成果如圖22-2所示。
圖 22-2
示例的解釋
此運用法式翻開本身的.cs文件,用於讀取。它鄙人面的代碼行中應用..字符串向上逐級導航兩個目次,找到該文件:
FileStream aFile = new FileStream("E:\\Workplace\\TestSolution\\Test.ConsoleApplication\\Program.cs",FileMode.Open);
上面兩行代碼完成查找任務,並從文件的詳細地位讀取字節:
aFile.Seek(135,SeekOrigin.Begin);
aFile.Read(byData,0,200);
第一行代碼將文件指針挪動到文件的第135個字節。在Program.cs中,這是namespace的 “n”;其後面的135個字符是using指令和相干的#region。第二即將接上去的200個字節讀入到byData字節數組中。
留意這兩行代碼封裝在try…catch塊中,以處置能夠拋出的異常。
try
{
aFile.Seek(135,SeekOrigin.Begin);
aFile.Read(byData,0,100);
}
catch(IOException e)
{
Console.WriteLine("An IO exception has been thrown!");
Console.WriteLine(e.ToString());
Console.ReadKey();
return;
}
文件IO觸及到的一切操作都可以拋出類型為IOException的異常。一切產物代碼都必需包括毛病處置,特別是處置文件體系時更是如斯。本章的一切示例都具有毛病處置的根本情勢。
從文件中獲得了字節數組後,就須要將其轉換為字符數組,以便在掌握台顯示它。為此,應用System.Text定名空間的Decoder類。此類用於將原始字節轉換為更有效的項,好比字符:
Decoder d = Encoding.UTF8.GetDecoder();
d.GetChars(byData, 0, byData.Length, charData, 0);
這些代碼基於UTF8編碼形式創立了Decoder對象。這就是Unicode編碼形式。然後挪用GetChars()辦法,此辦法提取字節數組,將它轉換為字符數組。完成以後,便可以將字符數組輸入到掌握台。
3. 寫入數據
向隨機拜訪文件中寫入數據的進程與從中讀取數據異常相似。起首須要創立一個字節數組;最簡略的方法是起首構建要寫入文件的字符數組。然後應用Encoder對象將其轉換為字節數組,其用法異常相似於Decoder。最初挪用Write()辦法,將字節數組傳送到文件中。
上面構建一個簡略的示例演示其進程。
嘗嘗看:將數據寫入隨機拜訪文件
(1) 在C:\BegVCSharp\Chapter22目次下創立一個新的掌握台運用法式WriteFile。
(2) 如上所示,在Program.cs文件頂部添加上面的using指令:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
(3) 在Main()辦法中添加上面的代碼:
static void Main(string[] args)
{
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;
}
}
(4) 運轉該運用法式。稍後就將其封閉。
(5) 導航到運用法式目次 —— 在目次中曾經保留了文件,由於我們應用了絕對途徑。目次位於WriteFile\bin\Debug文件夾。翻開Temp.txt文件。可以在文件中看到如圖22-3所示的文本。
圖 22-3
示例的解釋
此運用法式在本身的目次中翻開文件,並在文件中寫入了一個簡略的字符串。在構造上這個示例異常相似於後面的示例,只是用Write()取代了Read(),用Encoder取代了Decoder。
上面的代碼行應用String類的ToCharArray()靜態辦法,創立了字符數組。由於C#中的一切事物都是對象,文本“My pink half of the drainpipe.”現實上是一個String對象,所以乃至可以在字符串上挪用這些靜態辦法。
CharData = " My pink half of the drainpipe. ".ToCharArray();
上面的代碼行顯示了若何將字符數組轉換為FileStream對象須要的准確字節數組。
Encoder e = Endoding.UTF8.GetEncoder();
e.GetBytes(charData,0,charData.Length, byData,0,true);
此次,要基於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()辦法也有三個參數:要寫入的數組,開端寫入的數組下標和要寫入的字節數。