日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C#使用文件流FileStream和內存流MemoryStream操作底層字節數組byte[]_C#教程

作者:springsnow ? 更新時間: 2022-07-04 編程語言

一、Stream類概述

在.NET Framework中,文件和流是有區別的。

文件是存儲在磁盤上的數據集,它具有名稱和相應的路徑。當打開一個文件并對其進行讀/寫時,該文件就稱為流(stream)。

但是,流不僅僅是指打開的磁盤文件,還可以是網絡數據。.Net Framework允許在內存中創建流。此外,在控制臺應用程序中,鍵盤輸入和文本顯示都是流。?

1. Stream類

Stream類是所有流的抽象基類。

Stream類的主要屬性有CanRead、CanWrite(是否支持讀取寫入)、CanSeek(是否支持查找)、CanTimeout(是否可以超時)、Length(流的長度)、Position(獲取或設置當前流中的位置)、ReadTimeout/WriteTimeout(獲取或設置讀、寫操作的超時時間)

Stream類的主要方法有BeginRead/EndRead(開始結束異步讀操作),BeginWrite/EndWrite(開始結束異步寫操作)、Read(讀取字節序列)、ReadByte(讀取一個字節)、Seek(設置查找位置)、Write(寫入字節序列)、WriteByte(寫入一個字節)、 Flush(清除流的所有緩沖區并把緩沖數據寫入基礎設備)、Close(關閉當前流)。

2. FileStream、MemoryStream、BufferedStream和NetworkStream

  • 文件流類FileStream:以流的形式讀、寫、打開、關閉文件。另外,它還可以用來操作諸如:管道、標準輸入/輸出等其他與文件相關的操作系統句柄。
  • 內存流MemoryStream類:用來在內存中創建流,以暫時保持數據,因此有了它就無須在硬盤上創建臨時文件。它將數據封裝為無符號的字節序列,可以直接進行讀、寫、查找操作。
  • 緩沖流BufferedStream類:表示把流先添加到緩沖區,再進行數據的讀/寫操作。緩沖區是存儲區中用來緩存數據的字節塊。使用緩沖區可以減少訪問數據時對操作系統的調用次數,增強系統的讀/寫功能。
  • 網絡流NetworkStream類:為網絡訪問提供數據的基礎流。

注意,FileStream類也有緩沖功能,在創建FileStream類的實例時,只需要指定緩沖區的大小即可。

二、文件流類 FileStream

文件流類FileStream公開了以文件為主的Stream,既支持同步讀/寫操作,也支持異步讀/寫操作。

FileStream類的特點是操作字節和字節數組。這種方式不適合操作用字符數據構成的文本文件,適合處理非文本文件。

FileStream類提供了對文件的低級而復雜的操作,因此能夠實現更多高級的功能。

1、讀文件

Read,ReadByte()

//創建d:\file.txt的FileStream對象
FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate);
byte[] bData = new byte[fstream.Length];
//設置流當前位置為文件開始位置
fstream.Seek(0, SeekOrigin.Begin);

//將文件的內容存到字節數組中(緩存)
fstream.Read(bData, 0, bData.Length);
string result = Encoding.UTF8.GetString(bData);
Console.WriteLine(result);
if (fstream != null)
{
    //清除此流的緩沖區,使得所有緩沖的數據都寫入到文件中
    fstream.Flush();
    fstream.Close();
}

將字節數組轉成字符串顯示以外,字節數組還可以

//1、顯示成圖片
MemoryStream mstream = new MemoryStream(bData);
Image img = Image.FromStream(mstream);

 //2、作為值存儲到數據庫
SqlCommand comm = new SqlCommand();
comm.Parameters.Add("images", SqlDbType.Image).Value = bData;

 //3、寫入文件
File.WriteAllBytes("c:\aa.txt", bData);
FileStream fstream = new FileStream("c:\aa.txt");
fstream.Write(bData, 0, bData.Length);

2、分塊讀文件

int bufferSize = 5;
//創建d:\file.txt的FileStream對象
FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read, bufferSize, false);//false表示同步讀
byte[] bData = new byte[bufferSize];
//設置流當前位置為文件開始位置
fstream.Seek(0, SeekOrigin.Begin);
int bytesRead;
do
{
    //將文件的內容存到字節數組中(緩存)
    bytesRead = fstream.Read(bData, 0, bData.Length);
    string result = Encoding.UTF8.GetString(bData, 0, bytesRead);
    Console.WriteLine(result);
} while (bytesRead > 0);

if (fstream != null)
{
    //清除此流的緩沖區,使得所有緩沖的數據都寫入到文件中
    fstream.Flush();
    fstream.Close();
}

3、異步讀文件

ManualResetEvent mEvent = new ManualResetEvent(false);
int bufferSize = 5;
byte[] bData = new byte[bufferSize];
FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read, bufferSize, true);//false表示異步讀

AsyncCallback callback = null;
callback = (IAsyncResult ar) => 
  {
      int bytesRead = fstream.EndRead(ar);
      Console.WriteLine(Encoding.UTF8.GetString(bData, 0, bytesRead));
      if (bytesRead > 0)
      {
          fstream.BeginRead(bData, 0, bufferSize, callback, null);//繼續讀
      }
      else
      {
          fstream.Close();
          mEvent.Set();//讀取完畢,發送信號
      }
  };

IAsyncResult async = fstream.BeginRead(bData, 0, bufferSize, callback, null);
mEvent.WaitOne(5000, false);
Console.WriteLine("讀取完成");

備注:IAsyncResult 接口的成員

AsyncState 獲取一個用戶定義的對象,該對象限定或包含有關異步操作的信息。

AsyncWaitHandle 獲取用于等待異步操作完成的 WaitHandle。

CompletedSynchronously 獲取一個值,該值指示異步操作是否同步完成。

IsCompleted 獲取一個值,該值指示異步操作是否已完成。

4、寫文件

Write,WriteByte(Byte)

//創建d:\file.txt的FileStream對象
FileStream fstream = new FileStream(@"d:\file.txt", FileMode.OpenOrCreate);
byte[] bData = Encoding.UTF8.GetBytes("test filestream");
//設置流當前位置為文件開始位置
fstream.Seek(0, SeekOrigin.Begin);

//將字節數組中的內容寫入文件
fstream.Write(bData, 0, bData.Length);
if (fstream != null)
{
    //清除此流的緩沖區,使得所有緩沖的數據都寫入到文件中
    fstream.Flush();
    fstream.Close();
}

三、內存流MemoryStream類

內存流相對字節數組而言,具有流特有的特性,并且容量可自動增長。

在數據加密以及對長度不定的數據進行緩存等場合,使用內存流比較方便。

下面的代碼示例演示如何讀取和寫入將內存用作后備存儲的數據。

int count;
UnicodeEncoding uniEncoding = new UnicodeEncoding();

//創建要寫入流的數據 
byte[] firstString = uniEncoding.GetBytes("Invalid file path characters are: ");
byte[] secondString = uniEncoding.GetBytes(Path.GetInvalidPathChars());

using (MemoryStream memStream = new MemoryStream(100))
{
    // 將第一個字符串寫入流.
    memStream.Write(firstString, 0, firstString.Length);

    // 將第二個字符串按字節寫入流.
    count = 0;
    while (count < secondString.Length)
    {
        memStream.WriteByte(secondString[count++]);
    }

    // 將流屬性寫入控制臺.
    Console.WriteLine("Capacity = {0}, Length = {1}, Position = {2}\n", memStream.Capacity.ToString(), memStream.Length.ToString(), memStream.Position.ToString());

    // 將位置設置為流的開始.
    memStream.Seek(0, SeekOrigin.Begin);

    // 從流中讀取前20個字節.
    byte[] byteArray = new byte[memStream.Length];
    count = memStream.Read(byteArray, 0, 20);

    // 一個字節一個字節地讀取剩下的字節.
    while (count < memStream.Length)
    {
        byteArray[count++] = Convert.ToByte(memStream.ReadByte());
    }

    // 將字節數組解碼為char數組并將其寫入控制臺.
    char[] charArray = new char[uniEncoding.GetCharCount(byteArray, 0, count)];
    uniEncoding.GetDecoder().GetChars(byteArray, 0, count, charArray, 0);
    Console.WriteLine(charArray);
}

ToArray()與GetBuffer()的區別:

//將流中的數據復制到一個byte[]中,速度比GetBuffer()稍慢,但不會將無用的空數據放入buffer中。 
byte[] byteArray = memStream.ToArray();

//把流中的Buffer的引用傳遞出來,速度較快,Buffer的大小有流的Capacity決定的,但會傳無用的空數據。
byte[] byteArray = memStream.GetBuffer();

原文鏈接:https://www.cnblogs.com/springsnow/p/9428715.html

欄目分類
最近更新