010-數(shù)據(jù)流

流(stream)是對串行傳輸?shù)臄?shù)據(jù)(以字節(jié)為單位)的一種抽象表示,底層的設備可以是文件、外部設備、主存、網(wǎng)絡套接字等。


image.png

流提供三種基本操作:

  • 寫入:將數(shù)據(jù)從內(nèi)存緩沖區(qū)傳輸?shù)酵獠吭础?/li>
  • 讀?。簩?shù)據(jù)從外部源傳輸?shù)絻?nèi)存緩沖區(qū)。
  • 查找:重新設置流的當前位置,以便隨機讀寫。需要注意的是,并不是所有的流類型都能夠支持查找,例如,網(wǎng)絡流沒有當前位置的統(tǒng)一概念,因此一般不支持查找。

說明:Stream類提供有多種操作流的方法,其中Read和Write方法是Stream類及其派生類都提供的實現(xiàn),可支持在字節(jié)級別上對數(shù)據(jù)進行讀寫。實際的程序開發(fā)中,僅支持字節(jié)級別的數(shù)據(jù)處理會給開發(fā)人員帶來不便。

提供字符串或二進制方式讀取或寫入流。
優(yōu)點:
方法更靈活
部分方法可解決TCP消息通信無邊界問題


image.png

FileStream類

FileStream類繼承于Stream類,一個FileStream類的實例實際上代表一個磁盤文件,使用FileStream類可以對文件系統(tǒng)上的文件進行讀取、寫入、打開和關閉操作。

1、創(chuàng)建FileStream實例

(1)常用的構造函數(shù)具有三個參數(shù),例如:
FileStream(string path,FileMode mode   FileAccess access)
  • FileMode值用于指定當文件不存在時是否創(chuàng)建該文件,并確定是保留還是改寫現(xiàn)有文件的內(nèi)容


    image.png
  • FileAccess值是枚舉的一個成員,它控制對文件的訪問權限。表4-10列出了FileAccess所有的枚舉形式


    image.png
(2)File和FileInfo類也提供了創(chuàng)建FileStream對象的方法。

其中,OpenRead方法返回只讀文件流,OpenWrite方法返回只寫文件流。
例如:FileStream fs= File.OpenRead("C:\File1.txt");

2. 讀文件

在獲取FileStream實例之后,可利用FileStream對象的Read方法讀取文件中的數(shù)據(jù)。該方法用于從流中讀取字節(jié)塊并將該數(shù)據(jù)寫入給定字節(jié)數(shù)組中。其語法形式為:

  public override int Read(byte[] array,int offset,int count)

array : 存儲從文件流中讀取的數(shù)據(jù)。
offset : array字節(jié)數(shù)組中開始寫入數(shù)據(jù)的下標,一般為0。
size : 要從文件流中讀出字節(jié)的大小
返回值: 從FileStream中讀取的字節(jié)數(shù)。

3. 寫文件

Stream類及其所有子類都提供了Write方法,F(xiàn)ileStream類也不例外。該方法可將字節(jié)數(shù)組寫入流。語法形式為

    public override void Write (
    byte[] buffer,    //包含要寫入流的數(shù)據(jù)
    int offset,       // buffer中開始寫入數(shù)據(jù)的位置
    int size         //要寫入流的字節(jié)數(shù)
    )

MemoryStream類

MemoryStream類表示的是保存在內(nèi)存中的數(shù)據(jù)流。由內(nèi)存流封裝的數(shù)據(jù)可以在內(nèi)存中直接訪問。
MemoryStream類的構造函數(shù)具有多種重載形式,常用的構造函數(shù)有:
(1)MemoryStream ()
該構造函數(shù)初始分配的容量大小為0,隨著數(shù)據(jù)的不斷寫入容量可以不斷擴展。
(2)MemoryStream (Byte[])
該構造函數(shù)獲取的MemoryStream實例根據(jù)Byte[]字節(jié)數(shù)組進行初始化,并且實例容量大小固定即為字節(jié)數(shù)組的長度。由于實例的容量不能擴展,該構造函數(shù)一般用于數(shù)據(jù)不發(fā)生變化的場合。

  String testdata = "測試數(shù)據(jù)";
  char[] chars = testdata.ToCharArray();
  Byte[] bytes = new Byte[encoder.GetByteCount(chars, 0, chars.Length, true)];
  MemoryStream mem = new MemoryStream(bytes);

(3)MemoryStream (int capacity)
通過該構造函數(shù)創(chuàng)建初始容量大小為capacity的實例,并且實例容量大小可擴展。

網(wǎng)絡流

在System.Net.Sockets名稱空間中有一個NetworkStream類,用于通過網(wǎng)絡套接字發(fā)送和接收數(shù)據(jù)。
NetworkStream類支持對網(wǎng)絡數(shù)據(jù)的同步或異步訪問,它可被視為在數(shù)據(jù)來源端和接收端之間架設了一個數(shù)據(jù)通道.
只用于面向連接的數(shù)據(jù)傳輸


image.png

寫入操作是指從來源端內(nèi)存緩沖區(qū)到網(wǎng)絡上的數(shù)據(jù)傳輸;
讀取操作是從網(wǎng)絡上到接收端內(nèi)存緩沖區(qū)(如字節(jié)數(shù)組)的數(shù)據(jù)傳輸。


image.png

NetworkStream的用法
1、構造NetworkStream:
(1)利用TcpClient獲取網(wǎng)絡流對象,例如:
    TcpClient tcpClient=new TcpClient();
    tcpClient.Connect("www.abcd.com", 51888);
    NetworkStream networkStream = client.GetStream();

(2)利用Socket獲取網(wǎng)絡流對象,例如:

    NetworkStream myNetworkStream = new NetworkStream(mySocket);

2、發(fā)送數(shù)據(jù)

 public override void Write (byte[] buffer,int offset,int size )
image.png

3、接收數(shù)據(jù)

public override int Read ([InAttribute] [OutAttribute] byte[] buffer,int offset,int size) 

各參數(shù)的含義:
buffer :內(nèi)存中用于存儲從NetworkStream讀取的數(shù)據(jù)的位置。
offset:buffer 中開始將數(shù)據(jù)存儲到的位置。
Size:要從NetworkStream中讀取的字節(jié)數(shù)。
返回值 :
實際從NetworkStream中讀取的字節(jié)數(shù)。

Write方法:
  • NetworkStream對象的Write方法的返回值為void,該對象之所以不返回實際發(fā)送的字節(jié)數(shù),是因為能保證字節(jié)數(shù)組中的數(shù)據(jù)全部發(fā)送到TCP發(fā)送緩沖區(qū)中。
  • 在使用NetworkStream對象的Write方法前最好先檢測NetworkStream對象的Writeable屬性是否為True。
  • 如果發(fā)送的全部是單行文本信息,創(chuàng)建NetworkStream對象后,使用StreamReader和StreamWriter的ReadLine和WriteLine方法更簡單。
Read方法:
  • 調(diào)用NetworkStream類的Read方法前應確保NetworkStream對象的CanRead屬性值有效
  • 由于有可能TCP接收緩沖區(qū)還沒有接收到對方發(fā)送過來的指定長度的數(shù)據(jù),所以Read方法有一個整型的返回值。
  • 如果遠程主機關閉了套接字連接,并且此時有效數(shù)據(jù)已經(jīng)被完全接收,那么Read方法的返回值將會是0字節(jié)。

使用NetworkStream對象時,需要注意:
(1)通過DataAvailable屬性,可以迅速查看在緩沖區(qū)中是否有數(shù)據(jù)等待讀出。
(2)網(wǎng)絡流沒有當前位置的概念,因此它不支持對數(shù)據(jù)流的查找和隨機訪問,NetworkStream對象的CanSeek屬性始終返回false,讀取Position屬性和調(diào)用Seek方法時,都會引發(fā)NotSupportedException異常。
(3)網(wǎng)絡數(shù)據(jù)傳輸完成后,不要忘記用Close方法關閉NetworkStream對象。

StreamWriter與StreamReader類

可以看到所有的NetworkStream、MemoryStream、FileStream類都提供了以字節(jié)為基本單位的讀寫方法,但是這種方法需要首先將待寫入的數(shù)據(jù)轉化為字節(jié)數(shù)組后才能夠進行讀寫,當操作的是使用字符編碼的文本數(shù)據(jù)時,給開發(fā)人員帶來了不便。
StreamReader類主要完成以一種特定的編碼從流中讀取字符的功能,一般用于對文本數(shù)據(jù)的讀取操作;
StreamWriter類則主要以特定的編碼向流中寫入字符,一般用于對文本數(shù)據(jù)的寫操作。

1、創(chuàng)建StreamWriter實例

(1)StreamWriter (String path)
根據(jù)文件路徑創(chuàng)建以UTF-8編碼StreamWriter對象。例如:
StreamWriter sw= new StreamWriter ("C:\file1.txt");
(2)File及FileInfo類提供的CreateText方法。例如:
StreamWriter sw = File.CreateText ("C:\file1.txt");
(3)StreamWriter (Stream stream)
直接使用流對象創(chuàng)建StreamWriter對象。例如:
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter (fs);
如果已經(jīng)有了網(wǎng)絡流對象,同樣可以直接對網(wǎng)絡流對象進行封裝。
NetworkStream networkStream = client.GetStream();
StreamWriter sw = new StreamWriter (networkStream);

2、寫入文本

利用StreamWriter類將以一種特定的編碼向流中寫入字符。常見方法如下所示:
Write():向數(shù)據(jù)流寫入數(shù)據(jù)。Write()方法只是把傳送給它的字符串寫入流,但不追加換行符,因此可以使用Write()語句寫入完整的句子或段落。
WriteLine():向數(shù)據(jù)流寫入指定數(shù)據(jù)和一個換行符。
Close():關閉流。

3.創(chuàng)建StreamReader實例

(1)SteamReader (Stream stream)
利用流對象創(chuàng)建SteamReader對象。例如:
NetworkStream networkStream = client.GetStream();
SteamReader sr = new SteamReader (networkStream)
(2)SteamReader (String path)
如果需要處理的是文件流,則可以根據(jù)文件路徑創(chuàng)建一個以UTF8編碼的SteamReader對象。例如:
SteamReader sr = new SteamReader ("C:\file1.txt");

4.讀取文本

利用StremReader將以一種特定的編碼從流中讀取字符。常用方法有:
ReadLine():讀取數(shù)據(jù)直到遇到換行符(Unix)或者回車換行(Windows)為止。
ReadToEnd():讀取到文件尾的全部數(shù)據(jù)。
Peek():返回數(shù)據(jù)中下一個可用字符的編碼值,如到達文件末尾則Peek()方法的值為-1。
Close():關閉流,使用StreamReader之后,需要調(diào)用Close方法關閉流。

BinaryReader和BinaryWriter類

提供了BinaryReader和BinaryWriter類,用于以二進制模式讀寫流。
它們提供的一些讀寫方法是對稱的,比如針對不同的數(shù)據(jù)結構,BinaryReader提供了ReadByte、ReadBoolean、ReadInt、ReadInt16、ReadDouble、ReadString等方法,與之對應BinaryWriter則提供了多個重載Write方法。例如當Write方法傳遞的參數(shù)為Int32類型時,BinaryWriter類的Write方法將Int32類型數(shù)據(jù)轉化為長度為4的字節(jié)數(shù)組,并將字節(jié)流傳遞給一個Stream對象。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 一、基礎知識:1、JVM、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機...
    殺小賊閱讀 2,563評論 0 4
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • 關于Mongodb的全面總結 MongoDB的內(nèi)部構造《MongoDB The Definitive Guide》...
    中v中閱讀 32,304評論 2 89
  • 財富目標:4、5、6月每月月收入穩(wěn)定上萬元。 2018.5.1 一、好種子: 1、早課誦經(jīng),金剛心咒216遍,文殊...
    陳熱鬧閱讀 264評論 0 0
  • 昨天普天同降大雪,整個世界銀裝素裹,盡管出行不便,可也擋不住孩子們對大雪紛飛的熱愛。 仿佛每個人都向往白色的童話世...
    水默雪嶺閱讀 591評論 0 0

友情鏈接更多精彩內(nèi)容