010-数据流

流(stream)是对串行传输的数据(以字节为单位)的一种抽象表示,底层的设备可以是文件、外部设备、主存、网络套接字等。


image.png

流提供三种基本操作:

  • 写入:将数据从内存缓冲区传输到外部源。
  • 读取:将数据从外部源传输到内存缓冲区。
  • 查找:重新设置流的当前位置,以便随机读写。需要注意的是,并不是所有的流类型都能够支持查找,例如,网络流没有当前位置的统一概念,因此一般不支持查找。

说明:Stream类提供有多种操作流的方法,其中Read和Write方法是Stream类及其派生类都提供的实现,可支持在字节级别上对数据进行读写。实际的程序开发中,仅支持字节级别的数据处理会给开发人员带来不便。

提供字符串或二进制方式读取或写入流。
优点:
方法更灵活
部分方法可解决TCP消息通信无边界问题


image.png

FileStream类

FileStream类继承于Stream类,一个FileStream类的实例实际上代表一个磁盘文件,使用FileStream类可以对文件系统上的文件进行读取、写入、打开和关闭操作。

1、创建FileStream实例

(1)常用的构造函数具有三个参数,例如:
FileStream(string path,FileMode mode   FileAccess access)
  • FileMode值用于指定当文件不存在时是否创建该文件,并确定是保留还是改写现有文件的内容


    image.png
  • FileAccess值是枚举的一个成员,它控制对文件的访问权限。表4-10列出了FileAccess所有的枚举形式


    image.png
(2)File和FileInfo类也提供了创建FileStream对象的方法。

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

2. 读文件

在获取FileStream实例之后,可利用FileStream对象的Read方法读取文件中的数据。该方法用于从流中读取字节块并将该数据写入给定字节数组中。其语法形式为:

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

array : 存储从文件流中读取的数据。
offset : array字节数组中开始写入数据的下标,一般为0。
size : 要从文件流中读出字节的大小
返回值: 从FileStream中读取的字节数。

3. 写文件

Stream类及其所有子类都提供了Write方法,FileStream类也不例外。该方法可将字节数组写入流。语法形式为

    public override void Write (
    byte[] buffer,    //包含要写入流的数据
    int offset,       // buffer中开始写入数据的位置
    int size         //要写入流的字节数
    )

MemoryStream类

MemoryStream类表示的是保存在内存中的数据流。由内存流封装的数据可以在内存中直接访问。
MemoryStream类的构造函数具有多种重载形式,常用的构造函数有:
(1)MemoryStream ()
该构造函数初始分配的容量大小为0,随着数据的不断写入容量可以不断扩展。
(2)MemoryStream (Byte[])
该构造函数获取的MemoryStream实例根据Byte[]字节数组进行初始化,并且实例容量大小固定即为字节数组的长度。由于实例的容量不能扩展,该构造函数一般用于数据不发生变化的场合。

  String testdata = "测试数据";
  char[] chars = testdata.ToCharArray();
  Byte[] bytes = new Byte[encoder.GetByteCount(chars, 0, chars.Length, true)];
  MemoryStream mem = new MemoryStream(bytes);

(3)MemoryStream (int capacity)
通过该构造函数创建初始容量大小为capacity的实例,并且实例容量大小可扩展。

网络流

在System.Net.Sockets名称空间中有一个NetworkStream类,用于通过网络套接字发送和接收数据。
NetworkStream类支持对网络数据的同步或异步访问,它可被视为在数据来源端和接收端之间架设了一个数据通道.
只用于面向连接的数据传输


image.png

写入操作是指从来源端内存缓冲区到网络上的数据传输;
读取操作是从网络上到接收端内存缓冲区(如字节数组)的数据传输。


image.png

NetworkStream的用法
1、构造NetworkStream:
(1)利用TcpClient获取网络流对象,例如:
    TcpClient tcpClient=new TcpClient();
    tcpClient.Connect("www.abcd.com", 51888);
    NetworkStream networkStream = client.GetStream();

(2)利用Socket获取网络流对象,例如:

    NetworkStream myNetworkStream = new NetworkStream(mySocket);

2、发送数据

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

3、接收数据

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

各参数的含义:
buffer :内存中用于存储从NetworkStream读取的数据的位置。
offset:buffer 中开始将数据存储到的位置。
Size:要从NetworkStream中读取的字节数。
返回值 :
实际从NetworkStream中读取的字节数。

Write方法:
  • NetworkStream对象的Write方法的返回值为void,该对象之所以不返回实际发送的字节数,是因为能保证字节数组中的数据全部发送到TCP发送缓冲区中。
  • 在使用NetworkStream对象的Write方法前最好先检测NetworkStream对象的Writeable属性是否为True。
  • 如果发送的全部是单行文本信息,创建NetworkStream对象后,使用StreamReader和StreamWriter的ReadLine和WriteLine方法更简单。
Read方法:
  • 调用NetworkStream类的Read方法前应确保NetworkStream对象的CanRead属性值有效
  • 由于有可能TCP接收缓冲区还没有接收到对方发送过来的指定长度的数据,所以Read方法有一个整型的返回值。
  • 如果远程主机关闭了套接字连接,并且此时有效数据已经被完全接收,那么Read方法的返回值将会是0字节。

使用NetworkStream对象时,需要注意:
(1)通过DataAvailable属性,可以迅速查看在缓冲区中是否有数据等待读出。
(2)网络流没有当前位置的概念,因此它不支持对数据流的查找和随机访问,NetworkStream对象的CanSeek属性始终返回false,读取Position属性和调用Seek方法时,都会引发NotSupportedException异常。
(3)网络数据传输完成后,不要忘记用Close方法关闭NetworkStream对象。

StreamWriter与StreamReader类

可以看到所有的NetworkStream、MemoryStream、FileStream类都提供了以字节为基本单位的读写方法,但是这种方法需要首先将待写入的数据转化为字节数组后才能够进行读写,当操作的是使用字符编码的文本数据时,给开发人员带来了不便。
StreamReader类主要完成以一种特定的编码从流中读取字符的功能,一般用于对文本数据的读取操作;
StreamWriter类则主要以特定的编码向流中写入字符,一般用于对文本数据的写操作。

1、创建StreamWriter实例

(1)StreamWriter (String path)
根据文件路径创建以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)
直接使用流对象创建StreamWriter对象。例如:
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter (fs);
如果已经有了网络流对象,同样可以直接对网络流对象进行封装。
NetworkStream networkStream = client.GetStream();
StreamWriter sw = new StreamWriter (networkStream);

2、写入文本

利用StreamWriter类将以一种特定的编码向流中写入字符。常见方法如下所示:
Write():向数据流写入数据。Write()方法只是把传送给它的字符串写入流,但不追加换行符,因此可以使用Write()语句写入完整的句子或段落。
WriteLine():向数据流写入指定数据和一个换行符。
Close():关闭流。

3.创建StreamReader实例

(1)SteamReader (Stream stream)
利用流对象创建SteamReader对象。例如:
NetworkStream networkStream = client.GetStream();
SteamReader sr = new SteamReader (networkStream)
(2)SteamReader (String path)
如果需要处理的是文件流,则可以根据文件路径创建一个以UTF8编码的SteamReader对象。例如:
SteamReader sr = new SteamReader ("C:\file1.txt");

4.读取文本

利用StremReader将以一种特定的编码从流中读取字符。常用方法有:
ReadLine():读取数据直到遇到换行符(Unix)或者回车换行(Windows)为止。
ReadToEnd():读取到文件尾的全部数据。
Peek():返回数据中下一个可用字符的编码值,如到达文件末尾则Peek()方法的值为-1。
Close():关闭流,使用StreamReader之后,需要调用Close方法关闭流。

BinaryReader和BinaryWriter类

提供了BinaryReader和BinaryWriter类,用于以二进制模式读写流。
它们提供的一些读写方法是对称的,比如针对不同的数据结构,BinaryReader提供了ReadByte、ReadBoolean、ReadInt、ReadInt16、ReadDouble、ReadString等方法,与之对应BinaryWriter则提供了多个重载Write方法。例如当Write方法传递的参数为Int32类型时,BinaryWriter类的Write方法将Int32类型数据转化为长度为4的字节数组,并将字节流传递给一个Stream对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,365评论 0 4
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,898评论 2 89
  • 财富目标:4、5、6月每月月收入稳定上万元。 2018.5.1 一、好种子: 1、早课诵经,金刚心咒216遍,文殊...
    陈热闹阅读 242评论 0 0
  • 昨天普天同降大雪,整个世界银装素裹,尽管出行不便,可也挡不住孩子们对大雪纷飞的热爱。 仿佛每个人都向往白色的童话世...
    水默雪岭阅读 438评论 0 0