c#FileStream文件读写(转)
/C#文件流寫(xiě)文件,默認(rèn)追加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對(duì)象表示在磁盤或網(wǎng)絡(luò)路徑上指向文件的流。這個(gè)類提供了在文件中讀寫(xiě)字節(jié)的方法,但經(jīng)常使用StreamReader或 StreamWriter執(zhí)行這些功能。這是因?yàn)镕ileStream類操作的是字節(jié)和字節(jié)數(shù)組,而Stream類操作的是字符數(shù)據(jù)。字符數(shù)據(jù)易于使用, 但是有些操作,比如隨機(jī)文件訪問(wèn)(訪問(wèn)文件中間某點(diǎn)的數(shù)據(jù)),就必須由FileStream對(duì)象執(zhí)行,稍后對(duì)此進(jìn)行介紹。
還有幾種方法可以創(chuàng)建FileStream對(duì)象。構(gòu)造函數(shù)具有許多不同的重載版本,最簡(jiǎn)單的構(gòu)造函數(shù)僅僅帶有兩個(gè)參數(shù),即文件名和FileMode枚舉值。
?
| FileStream aFile = new FileStream(filename, FileMode.Member); |
?
FileMode枚舉有幾個(gè)成員,規(guī)定了如何打開(kāi)或創(chuàng)建文件。稍后介紹這些枚舉成員。另一個(gè)常用的構(gòu)造函數(shù)如下:
?
| FileStream aFile = new FileStream(filename, FileMode.Member, FileAccess. Member); |
?
第三個(gè)參數(shù)是FileAccess枚舉的一個(gè)成員,它指定了流的作用。FileAccess枚舉的成員如表22-6所示。
表? 22-6
| 成???員 ? | 說(shuō)????明 ? |
| Read ? | 打開(kāi)文件,用于只讀 ? |
| Write ? | 打開(kāi)文件,用于只寫(xiě) ? |
| ReadWrite ? | 打開(kāi)文件,用于讀寫(xiě) ? |
對(duì)文件進(jìn)行不是FileAccess枚舉成員指定的操作會(huì)導(dǎo)致拋出異常。此屬性的作用是,基于用戶的身份驗(yàn)證級(jí)別改變用戶對(duì)文件的訪問(wèn)權(quán)限。
在FileStream構(gòu)造函數(shù)不使用FileAccess枚舉參數(shù)的版本中,使用默認(rèn)值FileAccess. ReadWrite。
FileMode枚舉成員如表22-7所示。使用每個(gè)值會(huì)發(fā)生什么,取決于指定的文件名是否表示已有的文件。注意這個(gè)表中的項(xiàng)表示創(chuàng)建流時(shí)該流指向文件中的位置,下一節(jié)將詳細(xì)討論這個(gè)主題。除非特別說(shuō)明,否則流就指向文件的開(kāi)頭。
表? 22-7
| 成????員 ? | 文?件?存?在 ? | 文件不存在 ? |
| Append ? | 打開(kāi)文件,流指向文件的末尾,只能與枚舉FileAccess.Write聯(lián)合使用 ? | 創(chuàng)建一個(gè)新文件。只能與枚舉FileAccess.Write聯(lián)合使用 ? |
| Create ? | 刪除該文件,然后創(chuàng)建新文件 ? | 創(chuàng)建新文件 ? |
| CreateNew ? | 拋出異常 ? | 創(chuàng)建新文件 ? |
| Open ? | 打開(kāi)現(xiàn)有的文件,流指向文件的開(kāi)頭 ? | 拋出異常 ? |
| OpenOrCreate ? | 打開(kāi)文件,流指向文件的開(kāi)頭 ? | 創(chuàng)建新文件 ? |
| Truncate ? | 打開(kāi)現(xiàn)有文件,清除其內(nèi)容。流指向文件的開(kāi)頭,保留文件的初始創(chuàng)建日期 ? | 拋出異常 ? |
?
?
?
?
?
?
?
?
?
?
?
?
?
File和FileInfo類都提供了OpenRead()和OpenWrite()方法,更易于創(chuàng)建FileStream對(duì)象。前者打開(kāi)了只讀訪問(wèn)的文 件,后者只允許寫(xiě)入文件。這些都提供了快捷方式,因此不必以FileStream構(gòu)造函數(shù)的參數(shù)形式提供前面所有的信息。例如,下面的代碼行打開(kāi)了用于只 讀訪問(wèn)的Data.txt文件:
?
| FileStream aFile = File.OpenRead("Data.txt"); |
?
注意下面的代碼執(zhí)行同樣的功能:
?
| FileInfo aFileInfo = new FileInfo("Data.txt"); FileStream aFile = aFile.OpenRead(); |
?
1. 文件位置
FileStream類維護(hù)內(nèi)部文件指針,該指針指向文件中進(jìn)行下一次讀寫(xiě)操作的位置。在大多數(shù)情況下,當(dāng)打開(kāi)文件時(shí),它就指向文件的開(kāi)始位置,但是此指 針可以修改。這允許應(yīng)用程序在文件的任何位置讀寫(xiě),隨機(jī)訪問(wèn)文件,或直接跳到文件的特定位置上。當(dāng)處理大型文件時(shí),這非常省時(shí),因?yàn)轳R上可以定位到正確的 位置。
實(shí)現(xiàn)此功能的方法是Seek()方法,它有兩個(gè)參數(shù):第一個(gè)參數(shù)規(guī)定文件指針以字節(jié)為單位的移動(dòng)距離。第二個(gè)參數(shù)規(guī)定開(kāi)始計(jì)算的起始位置,用SeekOrigin枚舉的一個(gè)值表示。Seek Origin枚舉包含3個(gè)值:Begin、Current和End。
例如,下面的代碼行將文件指針移動(dòng)到文件的第8個(gè)字節(jié),其起始位置就是文件的第1個(gè)字節(jié):
?
| aFile.Seek(8,SeekOrigin.Begin); |
?
下面的代碼行將指針從當(dāng)前位置開(kāi)始向前移動(dòng)2個(gè)字節(jié)。如果在上面的代碼行之后執(zhí)行下面的代碼,文件指針就指向文件的第10個(gè)字節(jié):
?
| aFile.Seek(2,SeekOrigin.Current); |
?
注意讀寫(xiě)文件時(shí),文件指針也會(huì)改變。在讀取了10個(gè)字節(jié)之后,文件指針就指向被讀取的第10個(gè)字節(jié)之后的字節(jié)。
也可以規(guī)定負(fù)查找位置,這可以與SeekOrigin.End枚舉值一起使用,查找靠近文件末端的位置。下面的代碼會(huì)查找文件中倒數(shù)第5個(gè)字節(jié):
?
| aFile.Seek(–5, SeekOrigin.End); |
?
以這種方式訪問(wèn)的文件有時(shí)稱為隨機(jī)訪問(wèn)文件,因?yàn)閼?yīng)用程序可以訪問(wèn)文件中的任何位置。稍后介紹的Stream類可以連續(xù)地訪問(wèn)文件,不允許以這種方式操作文件指針。
2. 讀取數(shù)據(jù)
使用FileStream類讀取數(shù)據(jù)不像使用本章后面介紹的StreamReader類讀取數(shù)據(jù)那樣容易。這是因?yàn)镕ileStream類只能處理原始字 節(jié)(raw byte)。處理原始字節(jié)的功能使FileStream類可以用于任何數(shù)據(jù)文件,而不僅僅是文本文件。通過(guò)讀取字節(jié)數(shù)據(jù),FileStream對(duì)象可以用 于讀取圖像和聲音的文件。這種靈活性的代價(jià)是,不能使用FileStream類將數(shù)據(jù)直接讀入字符串,而使用StreamReader類卻可以這樣處理。 但是有幾種轉(zhuǎn)換類可以很容易地將字節(jié)數(shù)組轉(zhuǎn)換為字符數(shù)組,或者進(jìn)行相反的操作。
FileStream.Read()方法是從FileStream對(duì)象所指向的文件中訪問(wèn)數(shù)據(jù)的主要手段。這個(gè)方法從文件中讀取數(shù)據(jù),再把數(shù)據(jù)寫(xiě)入一個(gè)字 節(jié)數(shù)組。它有三個(gè)參數(shù):第一個(gè)參數(shù)是傳輸進(jìn)來(lái)的字節(jié)數(shù)組,用以接受FileStream對(duì)象中的數(shù)據(jù)。第二個(gè)參數(shù)是字節(jié)數(shù)組中開(kāi)始寫(xiě)入數(shù)據(jù)的位置。它通常 是0,表示從數(shù)組開(kāi)端向文件中寫(xiě)入數(shù)據(jù)。最后一個(gè)參數(shù)指定從文件中讀出多少字節(jié)。
下面的示例演示了從隨機(jī)訪問(wèn)文件中讀取數(shù)據(jù)。要讀取的文件實(shí)際是為此示例創(chuàng)建的類文件。
試試看:從隨機(jī)訪問(wèn)文件中讀取數(shù)據(jù)
(1) 在目錄C:\BegVCSharp\Chapter22下創(chuàng)建一個(gè)新的控制臺(tái)應(yīng)用程序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("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(); } |
?
(4) 運(yùn)行應(yīng)用程序。結(jié)果如圖22-2所示。
?
| 圖 22-2 |
?
示例的說(shuō)明
此應(yīng)用程序打開(kāi)自己的.cs文件,用于讀取。它在下面的代碼行中使用..字符串向上逐級(jí)導(dǎo)航兩個(gè)目錄,找到該文件:
?
| FileStream aFile = new FileStream("http://www.cnblogs.com/Program.cs",FileMode.Open); |
?
下面兩行代碼實(shí)現(xiàn)查找工作,并從文件的具體位置讀取字節(jié):
?
| aFile.Seek(135,SeekOrigin.Begin);aFile.Read(byData,0,200); |
?
第一行代碼將文件指針移動(dòng)到文件的第135個(gè)字節(jié)。在Program.cs中,這是namespace的 “n”;其前面的135個(gè)字符是using指令和相關(guān)的#region。第二行將接下來(lái)的200個(gè)字節(jié)讀入到byData字節(jié)數(shù)組中。
?
注意這兩行代碼封裝在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的異常。所有產(chǎn)品代碼都必須包含錯(cuò)誤處理,尤其是處理文件系統(tǒng)時(shí)更是如此。本章的所有示例都具有錯(cuò)誤處理的基本形式。
從文件中獲取了字節(jié)數(shù)組后,就需要將其轉(zhuǎn)換為字符數(shù)組,以便在控制臺(tái)顯示它。為此,使用System.Text命名空間的Decoder類。此類用于將原始字節(jié)轉(zhuǎn)換為更有用的項(xiàng),比如字符:
?
| Decoder d = Encoding.UTF8.GetDecoder(); d.GetChars(byData, 0, byData.Length, charData, 0); |
?
這些代碼基于UTF8編碼模式創(chuàng)建了Decoder對(duì)象。這就是Unicode編碼模式。然后調(diào)用GetChars()方法,此方法提取字節(jié)數(shù)組,將它轉(zhuǎn)換為字符數(shù)組。完成之后,就可以將字符數(shù)組輸出到控制臺(tái)。
3. 寫(xiě)入數(shù)據(jù)
向隨機(jī)訪問(wèn)文件中寫(xiě)入數(shù)據(jù)的過(guò)程與從中讀取數(shù)據(jù)非常類似。首先需要?jiǎng)?chuàng)建一個(gè)字節(jié)數(shù)組;最簡(jiǎn)單的辦法是首先構(gòu)建要寫(xiě)入文件的字符數(shù)組。然后使用Encoder對(duì)象將其轉(zhuǎn)換為字節(jié)數(shù)組,其用法非常類似于Decoder。最后調(diào)用Write()方法,將字節(jié)數(shù)組傳送到文件中。
下面構(gòu)建一個(gè)簡(jiǎn)單的示例演示其過(guò)程。
試試看:將數(shù)據(jù)寫(xiě)入隨機(jī)訪問(wèn)文件
(1) 在C:\BegVCSharp\Chapter22目錄下創(chuàng)建一個(gè)新的控制臺(tái)應(yīng)用程序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) 運(yùn)行該應(yīng)用程序。稍后就將其關(guān)閉。
(5) 導(dǎo)航到應(yīng)用程序目錄 —— 在目錄中已經(jīng)保存了文件,因?yàn)槲覀兪褂昧讼鄬?duì)路徑。目錄位于WriteFile\bin\Debug文件夾。打開(kāi)Temp.txt文件。可以在文件中看到如圖22-3所示的文本。
?
| 圖 22-3 |
?
示例的說(shuō)明
此應(yīng)用程序在自己的目錄中打開(kāi)文件,并在文件中寫(xiě)入了一個(gè)簡(jiǎn)單的字符串。在結(jié)構(gòu)上這個(gè)示例非常類似于前面的示例,只是用Write()代替了Read(),用Encoder代替了Decoder。
下面的代碼行使用String類的ToCharArray()靜態(tài)方法,創(chuàng)建了字符數(shù)組。因?yàn)镃#中的所有事物都是對(duì)象,文本“My pink half of the drainpipe.”實(shí)際上是一個(gè)String對(duì)象,所以甚至可以在字符串上調(diào)用這些靜態(tài)方法。
?
| CharData = " My pink half of the drainpipe. ".ToCharArray(); |
?
下面的代碼行顯示了如何將字符數(shù)組轉(zhuǎn)換為FileStream對(duì)象需要的正確字節(jié)數(shù)組。
?
| Encoder e = Endoding.UTF8.GetEncoder(); e.GetBytes(charData,0,charData.Length, byData,0,true); |
?
這次,要基于UTF8編碼方法來(lái)創(chuàng)建Encoder對(duì)象。也可以將Unicode用于解碼。這里在寫(xiě)入流之前,需要將字符數(shù)據(jù)編碼為正確的字節(jié)格式。在 GetBytes()方法中可以完成這些工作,它可以將字符數(shù)組轉(zhuǎn)換為字節(jié)數(shù)組,并將字符數(shù)組作為第一個(gè)參數(shù)(本例中的charData),將該數(shù)組中起 始位置的下標(biāo)作為第二個(gè)參數(shù)(0表示數(shù)組的開(kāi)頭)。第三個(gè)參數(shù)是要轉(zhuǎn)換的字符數(shù)量(charData.Length,charData數(shù)組中的元素個(gè) 數(shù))。第四個(gè)參數(shù)是在其中置入數(shù)據(jù)的字節(jié)數(shù)組(byData),第五個(gè)參數(shù)是在字節(jié)數(shù)組中開(kāi)始寫(xiě)入位置的下標(biāo)(0表示byData數(shù)組的開(kāi)頭)。
最后一個(gè)參數(shù)決定在結(jié)束后Encoder對(duì)象是否應(yīng)該更新其狀態(tài),即Encoder對(duì)象是否仍然保留它原來(lái)在字節(jié)數(shù)組中的內(nèi)存位置。這有助于以后調(diào)用 Encoder對(duì)象,但是當(dāng)只進(jìn)行單一調(diào)用時(shí),這就沒(méi)有什么意義。最后對(duì)Encoder的調(diào)用必須將此參數(shù)設(shè)置為true,以清空其內(nèi)存,釋放對(duì)象,用于 垃圾回收。
之后,使用Write()方法向FileStream寫(xiě)入字節(jié)數(shù)組就非常簡(jiǎn)單:
?
| aFile.Seek(0,SeekOrigin.Begin); aFile.Write(byData,0,byData.Length); |
?
與Read()方法一樣,Write()方法也有三個(gè)參數(shù):要寫(xiě)入的數(shù)組,開(kāi)始寫(xiě)入的數(shù)組下標(biāo)和要寫(xiě)入的字節(jié)數(shù)。
轉(zhuǎn)載于:https://www.cnblogs.com/zhoug2020/p/5821868.html
總結(jié)
以上是生活随笔為你收集整理的c#FileStream文件读写(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android Studio 添加 Ge
- 下一篇: c# 数据库连接