伊春信息港:C# 基础知识系列- 14 IO篇之入门IO

admin/2020-04-29/ 分类:科技/阅读:

0. 前言

在之前的章节中,大致先容了C#中的一些基本概念。这篇我们将先容一下C#的I/O操作,这将也是一个小连续剧。这是第一集,我们先来简朴领会一下C#中的I/O框架。

1. 什么是I/O

I/O 的全称是input/output,翻译过来就是输入/输出。对于一个系统或者计算机来说,键盘、U盘、网络接口、显示器、音响、摄像头等都是IO装备。那么,对于一个程序I/O又是什么呢?

对于程序而言,I/O就是与外界举行数据交流的方式。借用一句广告词,程序不生产数据,只是数据的搬用工。固然,正如XX还需要对水举行过滤、消毒等工序一样,程序也要对数据举行运算,以是也不完全算是搬用工,严酷来讲是加工厂。那么,I/O就是工厂的质料提供商和制品销售商。

在C# 中,I/O系统整体分为三个部门,后台存储流、装饰器流、流适配器,详细划分如下图所示:

在流与流之间,都是接纳字节数据举行交流,以是可以获得一个简朴的结论,I/O在程序中表现为字节省,换句话说I/O就是将种种数据转成字节的工具。

3. Stream 基类

C#中,所有流都是继续自Stream类,Stream类界说了流应该具有的行为和属性,使得开发人员可以忽略底层的操作系统和基础装备的详细细节。C#对流的处置忽略了读流和写流的区别,使其更像是一个管道,利便数据通信。流涉及到三个基本操作:

  • 读取 - 将数据从流中传输到数据结构中
  • 写入 - 将数据从数据源写入流中
  • 查找 - 对流中操作的当前位置举行查找和修改

由于流的特征,可能并不是所有的流都支持这三种操作,以是Stream提供了三个属性,以利便确认流是否支持这三种操作:

public abstract bool CanRead { get; } // 获取指示当前流是否支持读取的值 public abstract bool CanWrite { get; } // 获取指示当前流是否支持写入功效的值 public abstract bool CanSeek { get; } // 获取指示当前流是否支持查找功效的值 

以上这三个属性均由子类凭据自身特征确认是否支持读取、写入、查找,可能三个属性不会都为true,但绝对不会都为false。

下面是一些常见的流:

  • FileStream 用来操作文件的流
  • MemoryStream 操作内存的流
  • BufferedStream 缓存流,用来增强其他流的操作性能
  • NetworkStream 使用网络套接字举行操作的流
  • PipeStream 通过匿名和命名管道举行读取和写入
  • CryptoStream 用于将数据流链接到加密转换

4. 操作

C# 中I/O的操作都属于System.IO这个命名空间,在这个命名空间中C# 界说了文件相关的类、种种流、装饰器流、适配器以及其他一些相关的结构体。在以System.IO开头的命名空间中,C#对IO进一步扩展,并提供了流压缩息争压缩(System.IO.Compression),搜索和枚举文件系统元素(System.IO.Enumeration),提供用于使用内存映射文件的类(System.IO.MemoryMappedFiles)等内容。

我们先略过之后篇幅会先容的内容不提,先来看一下Stream类里主要的属性和方式:

1. 流里数据的长度

public abstract long Length { get; } 

当Stream工具的CanSeek为true时,也就是流支持搜索的时刻,可以通过这个属性确认流的长度,也就是有多少个字节的数据。

2. 流的位置

public abstract long Position { get; set; } 

同长度的前提条件一致,当Stream工具支持搜索的时刻,可以通过该属性确认流的位置或者修改流的位置。

3. 读取流里的数据

public abstract int Read (byte[] buffer, int offset, int count); public virtual int ReadByte (); 

这是两种差别的读取方式,第一种是每次读取多个字节的数据,第二个是每次只读一个字节的数据。这里来细细解说一下区别:

public abstract int Read (byte[] buffer, int offset, int count); 

示意流每次最多读取count个字节的数据,然后将数据放到buffer中,位置从下标为offset最先,并返回现实读取的字节数,若是流已经读完了,则返回0。这个过程中,Position会后移现实读取长度,若是流支持搜索,程序中可以挪用这个属性。

以是这里就有会这样的一个限制:offset count <= buffer.Length,换句话说,偏移量 最大读取数目不能大于缓存数组的长度。

由于这个方式返回一个现实读取长度,可能有人会这样判断是否读完:凭据返回的结果与count比,若是返回的长度小于count则以为流已经读完;否则流还没读完。

有一些流可能会杀青这样的效果,然则许多流并不能以此为依据来判断流是否读完,也许某一次读取长度小于count,然后再读一次发现又有数据了。这是由于IO在系统中属于高耗时操作,大部门情况下IO的性能和程序的运算速率相差甚远。以是经常会泛起这样的情景:流的长度是100,给了长度为100的缓存字节数组,然后第一次读取了10个字节,第二次读取了5个字节,这样一点一点的把这100个字节读取到。

以是,必须以返回值为0作为流的读完判断依据。

public virtual int ReadByte (); 

这个方式很简朴,每次从流里读取一个字节的数据,若是读取完成返回-1。可能有人会疑惑了,这个方式明显是读取一个字节,也就是个byte,那为什么返回类型是int呢?很简朴,由于byte没有负数,而int有。以是,当返回值不等于-1的时刻,可以放心的类型转换为byte。

4. 把数据写入流

public abstract void Write (byte[] buffer, int offset, int count); public virtual void WriteByte (byte value); 

流的写入与读取相比就简朴多了,至少我们不用判断流的位置。现在简朴剖析一下:

public abstract void Write (byte[] buffer, int offset, int count); 

示意从buffer的offset下标最先,取count个字节写入流里。以是,对offset、count的限制依旧,和不能大于数组的长度。写入乐成,流的位置会移动,否则将保持现有位置。

public virtual void WriteByte (byte value); 

这个方式就更简朴了,直接写一个字节给流。

5. 关闭或销毁流

流在操作完成之后,需要将其关闭以释放流所持有的文件或IO装备等资源。许多人在使用电脑的时刻,不能用QQ发送在内陆已经打开的excel文件,它会提醒文件被占用无法传输。这就是由于Excel打开了这个文件,就持有一个文件相关的流,以是QQ无法发送。解决办法很简朴,关掉excel软件即可。回到当前,也就是我们在使用完成之后必须关闭流。

那么我们该若何关闭流呢?挪用以下方式:

public virtual void Close (); 

C#虽然设置了Close方式,然则并不支持开发者在编写程序的时刻手动挪用Close方式,更推荐使用:

public void Dispose (); 

这个方式会将释放流所持有使用的资源,并关闭流。

当前需要注重的一个地方是,在把流关闭或释放之前把流里的数据推送到基础装备,即挪用:

public abstract void Flush (); 

有一些流设置了自动推送功效,若是遇到这种流则不需要手动挪用该方式。

对于流来说,一旦销毁或关闭,这个流就无法二次使用了,以是挪用了Close、Dispose之后再次实验读取/写入流都市报错

5. 本篇总结以及下篇预告

本篇内容也许先容了一下C#的IO系统以及一些基本操作,下一篇将先容若何操作文件。

更多内容烦请关注我的博客

,

Sunbet

Sunbet www.monetary-reproduction.com Sunbet仅需短短几秒,全天24小时无休止无限制免费注册,sunbet欢迎您的光临!

TAG:
阅读:
广告 330*360
广告 330*360
Sunbet_进入申博sunbet官网
微信二维码扫一扫
关注微信公众号
新闻自媒体 Copyright © 2002-2019 Sunbet 版权所有
二维码
意见反馈 二维码