五月综合缴情婷婷六月,色94色欧美sute亚洲线路二,日韩制服国产精品一区,色噜噜一区二区三区,香港三级午夜理伦三级三

您現(xiàn)在的位置: 365建站網(wǎng) > 365文章 > c#/vb.net中FileStream類文件讀寫

c#/vb.net中FileStream類文件讀寫

文章來源:365jz.com     點擊數(shù):1141    更新時間:2018-06-04 13:09   參與評論

FileStream類的使用

1、什么是FileStream類

  FileStream 類對文件系統(tǒng)上的文件進行讀取、寫入、打開和關(guān)閉操作,并對其他與文件相關(guān)的操作系統(tǒng)句柄進行操作,如管道、標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出。讀寫操作可以指定為同步或異步操作。FileStream 對輸入輸出進行緩沖,從而提高性能。——MSDN

  簡單點說:FileStream類可以對任意類型的文件進行讀取操作,而且我們也可以根據(jù)自己需要來指定每一次讀取字節(jié)長度,以此減少內(nèi)存的消耗,提高讀取效率。

使用 FileStream 類來讀取、 寫入、 打開和關(guān)閉文件系統(tǒng)上的文件以及處理其他包括管道、 標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出的文件相關(guān)的操作系統(tǒng)句柄。 您可以使用 Read, ,Write, ,CopyTo, ,和 Flush 方法來執(zhí)行同步操作時,或 ReadAsync, ,WriteAsync, ,CopyToAsync, ,和 FlushAsync 方法來執(zhí)行異步操作。 使用異步方法以在不阻塞主線程的情況下執(zhí)行占用大量資源的文件。 在 Windows 8.x 應(yīng)用商店 應(yīng)用或 桌面 應(yīng)用中一個耗時的流操作可能阻塞 UI 線程并讓您的應(yīng)用看起來好像不工作時,這種性能的考慮就顯得尤為重要了。 FileStream 緩沖輸入和輸出來更好的性能。


當(dāng) FileStream 對象不具有獨占持有其句柄,另一個線程可以同時訪問的文件句柄和更改與文件句柄關(guān)聯(lián)的操作系統(tǒng)的文件指針的位置。 在此情況下中的緩存位置 FileStream 對象,并在緩沖區(qū)中緩存的數(shù)據(jù)可能會損害。 FileStream 對象定期執(zhí)行來訪問緩存的緩沖區(qū),以確保操作系統(tǒng)的句柄位置與緩存的位置使用相同的方法對檢查 FileStream 對象。

如果句柄位置發(fā)生意外的更改對的調(diào)用中檢測到 Read 方法,.NET Framework 放棄緩沖區(qū)的內(nèi)容,并再次從文件讀取流。 這會影響性能,具體取決于文件的大小和任何其他進程可能會影響文件流的當(dāng)前位置。

如果句柄位置發(fā)生意外的更改對的調(diào)用中檢測到 Write 方法時,緩沖區(qū)的內(nèi)容將被丟棄和 IOException 則會引發(fā)異常。

一個 FileStream 對象不會產(chǎn)生獨占持有其句柄時任一 SafeFileHandle 屬性訪問要公開句柄或 FileStream 對象都提供了 SafeFileHandle 其構(gòu)造函數(shù)中的屬性。

2、File和FileStream的區(qū)別

  直觀點:File是一個靜態(tài)類;FileStream是一個非靜態(tài)類。

  File:是一個文件的類,對文件進行操作。其內(nèi)部封裝了對文件的各種操作(MSDN:提供用于創(chuàng)建、復(fù)制、刪除、移動和打開單一文件的靜態(tài)方法,并協(xié)助創(chuàng)建FileStream對象)。

  FileStream:文件流的類。對txt,xml,avi等文件進行內(nèi)容寫入、讀取、復(fù)制...時候需要使用的一個工具。

  打個形象的比喻。File是筆記本,需要Filestream的這個筆才能寫.

  換而言之,記事本是一個文件,可以用File操作,里面的內(nèi)容需要用FileStream來操作。

注:FileStream是對字節(jié)操作的(任何文件)。



//非靜態(tài)類,創(chuàng)建對象調(diào)用方法
            using (FileStream Fsread = new FileStream(@"C:\Users\Administrator\Desktop\測試文檔.txt", FileMode.OpenOrCreate, FileAccess.Read))
            {
                byte[] b = new byte[50]; 
                //用來限定每次的讀取字節(jié)數(shù),也可以byte[] b=new byte[Fsread.Length];
                string s = "";
                while (true)
                {
                    int r = Fsread.Read(b, 0, b.Length);
                    if (r == 0)
                        break;
                    s += Encoding.UTF8.GetString(b, 0, r);
                }
                Console.Write(s);
                // Fsread.Close();//關(guān)閉當(dāng)前流
                // Fsread.Dispose();//釋放流所使用的資源
            }



將創(chuàng)建文件流的過程寫在using中,可以自動幫助釋放流所占用的資源。


//文件流的寫入
            using (FileStream fswrite = new FileStream(@"C:\Users\Administrator\Desktop\測試文檔.txt", FileMode.OpenOrCreate, FileAccess.Write))
            {
                string str = "一切皆有可能";
                byte[] buffer = Encoding.UTF8.GetBytes(str);
                fswrite.Write(buffer, 0, buffer.Length);
            }


無論是讀還是寫,都要借助一個緩沖區(qū)buffer來存取字節(jié)。

注意:在寫入和讀取時,字符編碼格式要相同,不然會出現(xiàn)亂碼。

Encoding.UTF8.GetBytes(str);
Encoding.UTF8.GetString(b, 0, r);


//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對象表示在磁盤或網(wǎng)絡(luò)路徑上指向文件的流。這個類提供了在文件中讀寫字節(jié)的方法,但經(jīng)常使用StreamReader或StreamWriter執(zhí)行這些功能。這是因為FileStream類操作的是字節(jié)和字節(jié)數(shù)組,而Stream類操作的是字符數(shù)據(jù)。字符數(shù)據(jù)易于使用,但是有些操作,比如隨機文件訪問(訪問文件中間某點的數(shù)據(jù)),就必須由FileStream對象執(zhí)行,稍后對此進行介紹。

還有幾種方法可以創(chuàng)建FileStream對象。構(gòu)造函數(shù)具有許多不同的重載版本,最簡單的構(gòu)造函數(shù)僅僅帶有兩個參數(shù),即文件名和FileMode枚舉值。


FileStream aFile = new FileStream(filename, FileMode.Member);


FileMode枚舉有幾個成員,規(guī)定了如何打開或創(chuàng)建文件。稍后介紹這些枚舉成員。另一個常用的構(gòu)造函數(shù)如下:


FileStream aFile = new FileStream(filename, FileMode.Member, FileAccess. Member);


第三個參數(shù)是FileAccess枚舉的一個成員,它指定了流的作用。FileAccess枚舉的成員如表22-6所示。

表  22-6

   

    

Read

打開文件,用于只讀

Write

打開文件,用于只寫

ReadWrite

打開文件,用于讀寫

對文件進行不是FileAccess枚舉成員指定的操作會導(dǎo)致拋出異常。此屬性的作用是,基于用戶的身份驗證級別改變用戶對文件的訪問權(quán)限。

在FileStream構(gòu)造函數(shù)不使用FileAccess枚舉參數(shù)的版本中,使用默認值FileAccess. ReadWrite。

FileMode枚舉成員如表22-7所示。使用每個值會發(fā)生什么,取決于指定的文件名是否表示已有的文件。注意這個表中的項表示創(chuàng)建流時該流指向文件中的位置,下一節(jié)將詳細討論這個主題。除非特別說明,否則流就指向文件的開頭。

表  22-7

 

    

   

文件不存在

Append

打開文件,流指向文件的末尾,只能與枚舉FileAccess.Write聯(lián)合使用

創(chuàng)建一個新文件。只能與枚舉FileAccess.Write聯(lián)合使用

Create

刪除該文件,然后創(chuàng)建新文件

創(chuàng)建新文件

CreateNew

拋出異常

創(chuàng)建新文件

Open

打開現(xiàn)有的文件,流指向文件的開頭

拋出異常

OpenOrCreate

打開文件,流指向文件的開頭

創(chuàng)建新文件

Truncate

打開現(xiàn)有文件,清除其內(nèi)容。流指向文件的開頭,保留文件的初始創(chuàng)建日期

拋出異常

 

File和FileInfo類都提供了OpenRead()和OpenWrite()方法,更易于創(chuàng)建FileStream對象。前者打開了只讀訪問的文件,后者只允許寫入文件。這些都提供了快捷方式,因此不必以FileStream構(gòu)造函數(shù)的參數(shù)形式提供前面所有的信息。例如,下面的代碼行打開了用于只讀訪問的Data.txt文件:


FileStream aFile = File.OpenRead("Data.txt");


注意下面的代碼執(zhí)行同樣的功能:


FileInfo aFileInfo = new FileInfo("Data.txt");
FileStream aFile = aFile.OpenRead();


1. 文件位置

FileStream類維護內(nèi)部文件指針,該指針指向文件中進行下一次讀寫操作的位置。在大多數(shù)情況下,當(dāng)打開文件時,它就指向文件的開始位置,但是此指針可以修改。這允許應(yīng)用程序在文件的任何位置讀寫,隨機訪問文件,或直接跳到文件的特定位置上。當(dāng)處理大型文件時,這非常省時,因為馬上可以定位到正確的位置。

實現(xiàn)此功能的方法是Seek()方法,它有兩個參數(shù):第一個參數(shù)規(guī)定文件指針以字節(jié)為單位的移動距離。第二個參數(shù)規(guī)定開始計算的起始位置,用SeekOrigin枚舉的一個值表示。Seek Origin枚舉包含3個值:Begin、Current和End。

例如,下面的代碼行將文件指針移動到文件的第8個字節(jié),其起始位置就是文件的第1個字節(jié):


aFile.Seek(8,SeekOrigin.Begin);


下面的代碼行將指針從當(dāng)前位置開始向前移動2個字節(jié)。如果在上面的代碼行之后執(zhí)行下面的代碼,文件指針就指向文件的第10個字節(jié):


aFile.Seek(2,SeekOrigin.Current);


注意讀寫文件時,文件指針也會改變。在讀取了10個字節(jié)之后,文件指針就指向被讀取的第10個字節(jié)之后的字節(jié)。

也可以規(guī)定負查找位置,這可以與SeekOrigin.End枚舉值一起使用,查找靠近文件末端的位置。下面的代碼會查找文件中倒數(shù)第5個字節(jié):


aFile.Seek(–5, SeekOrigin.End);


以這種方式訪問的文件有時稱為隨機訪問文件,因為應(yīng)用程序可以訪問文件中的任何位置。稍后介紹的Stream類可以連續(xù)地訪問文件,不允許以這種方式操作文件指針。

2. 讀取數(shù)據(jù)

使用FileStream類讀取數(shù)據(jù)不像使用本章后面介紹的StreamReader類讀取數(shù)據(jù)那樣容易。這是因為FileStream類只能處理原始字節(jié)(raw byte)。處理原始字節(jié)的功能使FileStream類可以用于任何數(shù)據(jù)文件,而不僅僅是文本文件。通過讀取字節(jié)數(shù)據(jù),F(xiàn)ileStream對象可以用于讀取圖像和聲音的文件。這種靈活性的代價是,不能使用FileStream類將數(shù)據(jù)直接讀入字符串,而使用StreamReader類卻可以這樣處理。但是有幾種轉(zhuǎn)換類可以很容易地將字節(jié)數(shù)組轉(zhuǎn)換為字符數(shù)組,或者進行相反的操作。

FileStream.Read()方法是從FileStream對象所指向的文件中訪問數(shù)據(jù)的主要手段。這個方法從文件中讀取數(shù)據(jù),再把數(shù)據(jù)寫入一個字節(jié)數(shù)組。它有三個參數(shù):第一個參數(shù)是傳輸進來的字節(jié)數(shù)組,用以接受FileStream對象中的數(shù)據(jù)。第二個參數(shù)是字節(jié)數(shù)組中開始寫入數(shù)據(jù)的位置。它通常是0,表示從數(shù)組開端向文件中寫入數(shù)據(jù)。最后一個參數(shù)指定從文件中讀出多少字節(jié)。

下面的示例演示了從隨機訪問文件中讀取數(shù)據(jù)。要讀取的文件實際是為此示例創(chuàng)建的類文件。

試試看:從隨機訪問文件中讀取數(shù)據(jù)

(1) 在目錄C:\BegVCSharp\Chapter22下創(chuàng)建一個新的控制臺應(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īng)用程序。結(jié)果如圖22-2所示。


圖 22-2


示例的說明
此應(yīng)用程序打開自己的.cs文件,用于讀取。它在下面的代碼行中使用..字符串向上逐級導(dǎo)航兩個目錄,找到該文件:


FileStream aFile = new FileStream("http://www.cnblogs.com/Program.cs",FileMode.Open);


下面兩行代碼實現(xiàn)查找工作,并從文件的具體位置讀取字節(jié):


   aFile.Seek(135,SeekOrigin.Begin);
   aFile.Read(byData,0,200);


第一行代碼將文件指針移動到文件的第135個字節(jié)。在Program.cs中,這是namespace的 “n”;其前面的135個字符是using指令和相關(guān)的#region。第二行將接下來的200個字節(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)品代碼都必須包含錯誤處理,尤其是處理文件系統(tǒng)時更是如此。本章的所有示例都具有錯誤處理的基本形式。

從文件中獲取了字節(jié)數(shù)組后,就需要將其轉(zhuǎn)換為字符數(shù)組,以便在控制臺顯示它。為此,使用System.Text命名空間的Decoder類。此類用于將原始字節(jié)轉(zhuǎn)換為更有用的項,比如字符:


Decoder d = Encoding.UTF8.GetDecoder();
d.GetChars(byData, 0, byData.Length, charData, 0);


這些代碼基于UTF8編碼模式創(chuàng)建了Decoder對象。這就是Unicode編碼模式。然后調(diào)用GetChars()方法,此方法提取字節(jié)數(shù)組,將它轉(zhuǎn)換為字符數(shù)組。完成之后,就可以將字符數(shù)組輸出到控制臺。

3. 寫入數(shù)據(jù)

向隨機訪問文件中寫入數(shù)據(jù)的過程與從中讀取數(shù)據(jù)非常類似。首先需要創(chuàng)建一個字節(jié)數(shù)組;最簡單的辦法是首先構(gòu)建要寫入文件的字符數(shù)組。然后使用Encoder對象將其轉(zhuǎn)換為字節(jié)數(shù)組,其用法非常類似于Decoder。最后調(diào)用Write()方法,將字節(jié)數(shù)組傳送到文件中。

下面構(gòu)建一個簡單的示例演示其過程。

試試看:將數(shù)據(jù)寫入隨機訪問文件

(1) 在C:\BegVCSharp\Chapter22目錄下創(chuàng)建一個新的控制臺應(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īng)用程序。稍后就將其關(guān)閉。

(5) 導(dǎo)航到應(yīng)用程序目錄 —— 在目錄中已經(jīng)保存了文件,因為我們使用了相對路徑。目錄位于WriteFile\bin\Debug文件夾。打開Temp.txt文件??梢栽谖募锌吹饺鐖D22-3所示的文本。


圖 22-3


示例的說明
此應(yīng)用程序在自己的目錄中打開文件,并在文件中寫入了一個簡單的字符串。在結(jié)構(gòu)上這個示例非常類似于前面的示例,只是用Write()代替了Read(),用Encoder代替了Decoder。

下面的代碼行使用String類的ToCharArray()靜態(tài)方法,創(chuàng)建了字符數(shù)組。因為C#中的所有事物都是對象,文本“My pink half of the drainpipe.”實際上是一個String對象,所以甚至可以在字符串上調(diào)用這些靜態(tài)方法。


CharData = " My pink half of the drainpipe. ".ToCharArray();


下面的代碼行顯示了如何將字符數(shù)組轉(zhuǎn)換為FileStream對象需要的正確字節(jié)數(shù)組。


Encoder e = Endoding.UTF8.GetEncoder();
e.GetBytes(charData,0,charData.Length, byData,0,true);


這次,要基于UTF8編碼方法來創(chuàng)建Encoder對象。也可以將Unicode用于解碼。這里在寫入流之前,需要將字符數(shù)據(jù)編碼為正確的字節(jié)格式。在GetBytes()方法中可以完成這些工作,它可以將字符數(shù)組轉(zhuǎn)換為字節(jié)數(shù)組,并將字符數(shù)組作為第一個參數(shù)(本例中的charData),將該數(shù)組中起始位置的下標(biāo)作為第二個參數(shù)(0表示數(shù)組的開頭)。第三個參數(shù)是要轉(zhuǎn)換的字符數(shù)量(charData.Length,charData數(shù)組中的元素個數(shù))。第四個參數(shù)是在其中置入數(shù)據(jù)的字節(jié)數(shù)組(byData),第五個參數(shù)是在字節(jié)數(shù)組中開始寫入位置的下標(biāo)(0表示byData數(shù)組的開頭)。

最后一個參數(shù)決定在結(jié)束后Encoder對象是否應(yīng)該更新其狀態(tài),即Encoder對象是否仍然保留它原來在字節(jié)數(shù)組中的內(nèi)存位置。這有助于以后調(diào)用Encoder對象,但是當(dāng)只進行單一調(diào)用時,這就沒有什么意義。最后對Encoder的調(diào)用必須將此參數(shù)設(shè)置為true,以清空其內(nèi)存,釋放對象,用于垃圾回收。

之后,使用Write()方法向FileStream寫入字節(jié)數(shù)組就非常簡單:


aFile.Seek(0,SeekOrigin.Begin);
aFile.Write(byData,0,byData.Length);


與Read()方法一樣,Write()方法也有三個參數(shù):要寫入的數(shù)組,開始寫入的數(shù)組下標(biāo)和要寫入的字節(jié)數(shù)。



下面給出的一個vb.net中應(yīng)用的例子,單擊按鈕1創(chuàng)建一個文件,將文本框1里的文本寫入到該文件。單擊按鈕2把由單擊按鈕1創(chuàng)建的文件內(nèi)容讀取出來,顯示在文本框2里;完整代碼如下:

Imports System.IO
Imports System.Text
Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim Myw As New FileStream(Application.StartupPath & "\實驗文件.txt", FileMode.Create)
        Dim MyBytes As Byte() = New UTF8Encoding().GetBytes(TextBox1.Text)
        Dim MyB_Write As BinaryWriter = New BinaryWriter(Myw)
        MyB_Write.Write(MyBytes, 0, MyBytes.Length)
        Myw.Close()
    End Sub
 
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim Myr As New FileStream(Application.StartupPath & "\實驗文件.txt", FileMode.Open, FileAccess.Read)
        Myr.Position = 0
        Dim MyB_Read As New BinaryReader(Myr)
        Dim MyFileLength As Integer = CInt(Myr.Length - Myr.Position) - 1
        Dim MyFileData(MyFileLength) As Char
        MyB_Read.Read(MyFileData, 0, MyFileLength)
        Myr.Close()
        TextBox2.Text = ""
        Dim i As Integer
        For i = LBound(MyFileData) To UBound(MyFileData)
            TextBox2.Text = TextBox2.Text & MyFileData(i)
        Next
    End Sub
End Class


如對本文有疑問,請?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會為你解答?。?點擊進入論壇

發(fā)表評論 (1141人查看,0條評論)
請自覺遵守互聯(lián)網(wǎng)相關(guān)的政策法規(guī),嚴禁發(fā)布色情、暴力、反動的言論。
昵稱:
最新評論
------分隔線----------------------------

其它欄目

· 建站教程
· 365學(xué)習(xí)

業(yè)務(wù)咨詢

· 技術(shù)支持
· 服務(wù)時間:9:00-18:00
365建站網(wǎng)二維碼

Powered by 365建站網(wǎng) RSS地圖 HTML地圖

copyright © 2013-2024 版權(quán)所有 鄂ICP備17013400號