一.什么是I/0流?

  英文翻译:Input/Output,在程序里简单的理解为读写数据操作数据的意思。流操作是为了解决体积大数据占用太多的内存,就是分段进行操作。就跟我们吃饭一样,一口一口的吃,还没见过谁直接一口吃完的。流就是细水长流。

  在我们强大的Net中,就是微软为了简化我们的工作,为了我们能对一系列的对象进行行操作,读写。NetFrameWork为我们.Net程序员提供了各种各样的类方便我们操作。他们都在Sytem.IO这个命 名空间,我们下面的内容就是要对这些类做详细的说明。

二.有几种流,这几种流的区别是什么,怎么用?

1.常用的流

文件流 FileStream

内存流MemoryStream

网络流NetworkStream

 这个三个流都是从Stream继承下来的,还有几个不常用的流。

2.Stream介绍

可以看到Stream类是抽象类,定义了流应有的一些基本操作的声明,具体实现由继承它的具体子类流实现。

属性说明:

    Position 表示流的位置,

    Length 表示流的长度。

         CanWrite表示当前流是否可以写入。

    CanTimeOut表示当前的流是否可以超时。

    CanSeek表示 获取指示当前流是否支持查找功能的值。

    CanRead表示当前流是否支持读取操作。

    ReadTimeout 设置读取操作时候的超时时间。

    WriteTimeout 设置写入操作的时候超时的时间。

方法说明下:

  Synchronized:MSDN 上解释是指定的 Stream 对象周围创建线程安全(同步)包装。这个解释我也不是很明白,应该就是给流包装一下,返回值还是一个流。

  BeginRead:开始异步读操作,参数1:是一个byte数组,作为流的缓冲区,参数2是开始读取的位置,第三个参数是读取的读取的长度。第四个参数是一个回调用委托参数,这个参数的作用,是在流读取完成之后执行某些操作,第五个参数就是一个自定义的对象状态。用与其他的流区分。这个参数不管它,占时我也不知道有啥用。

  BeginWrite:同理我就不说了。

  Close:我就不说了。

  CoptyToStream:从当前流中读取字节并将其写入到另一流中。

  CoptyToAsync:从名字就可以看出区别的和上面的功能一样,只是异步读取。

  Read:开始读取操作,和第一个方法一样,但是不是异步操作,返回值是读到的字节数字,返回0代表,到达流的结尾,读完了。

  Write :同理。

  ReadAsync:取代了BeginRead

  ReadByte:读取一个字节,并将流的位置提升一个字节,意思就是从你读完的地方接着读,不会从头读。

  Seek:设置当前流的位置。

  SetLength:设置当前流的长度。

Stream定义的基础方法就这么多,各种方法还有几个重载版本。详细了解的可以去看看MSDN官方文档。Stream类是一个抽象类,只定义方法在声明,具体实现由派生其的子类去实现。也就是接下来要要讲解的:

  文件流FileStream

  内存流 MemoryStream

  和网络流NetWorkStream(System.Net.Sockets命名空间下,不同于之前两个)

3.FileStream流

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace IOTest
{
class Program
{
static void Main(string[] args)
{ //创建流实例。
FileStream filestrem = new FileStream(@"d:\一小时小超人.txt", FileMode.Create);
string message = "我的名字叫:一小时小超人啊";
byte[] bytes = Encoding.UTF8.GetBytes(message); //写入字符串
filestrem.Write(bytes, 0, bytes.Length); }
}
}

这是时候我们去D盘可以发现我们已经成功写入了。但是这个地方有一个问题,首先我们将代码稍微改变一下。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace IOTest
{
class Program
{
static void Main(string[] args)
{ //创建流实例。
FileStream filestream = new FileStream(@"d:\一小时小超人.txt", FileMode.Create);
string message = "我的名字叫:一小时小超人啊";
byte[] bytes = Encoding.UTF8.GetBytes(message); //写入字符串
filestream.Write(bytes, 0, bytes.Length);
Console.ReadKey(); }
}
}

注意:

  上面代码地方标注红色的代码是我添加的,这时候我们再次运行时候控制台界面不会一闪而过,这个时候我们手动关闭控制台程序,然后在去D盘看我们创建的文件。您会发现这个时候,字符没有被写进来。这是因为流的写入有一个缓冲区的概念。因为I0操作是很耗时的,如果读到一个字节,就写一个字节。那这样整个过程就很慢。

  这个原理就和网站一样。一个操作要多次请求服务端一样。将多次请求并为一次。这样做节约了很多性能。IO流也是一样。它将读取的字节先写到缓冲区里面。然后一次性写入文件。这样节约了很大的性能。所以Write操作只是将字节写入缓冲区,而不是真正的写入文件。那么真正的写入文件的操作是什么呢?

  FileStrem为了我们提供了Flush这个方法将缓冲区的内容写入文件,清除缓冲区。所以刚刚我们手动关闭控制台。导致发生异常。写入失败。这时候聪明的同学可能会有疑问,第一次的时候也没有调用Flush这个方法,也成功的写入了。这是因为什么呢?这是因为程序正常执行结束的时候,销毁这个对象的时候,系统会为了保证缓冲区的文件写入文件中,会自动帮我们调用这个Flush方法,FileStream中很多地方都调用了Flush。例如:Close()和Dispose()。

  说到 FileStream的读写就不得不说到StreamRead和StreamWrite这个两个是通用读写器类。对流的操作都可以用它。

  之前一直没搞清楚这个与FileStream区别,感觉这个两个差不多,但是还是有一点区别的。

  两者最大的区别:FileStream是操作字节和字节数组,可以操作任何类型的文件,但是StreamRead主要操作的是字符串。

  叙述结束,从下面掏一手代码说话!

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace IOTest
{
class Program
{
static void Main(string[] args)
{ //创建流实例。
FileStream filestrem = new FileStream(@"d:\一小时小超人.txt", FileMode.Create);
//string message = "我的名字叫:一小时小超人啊";
//byte[] bytes = Encoding.UTF8.GetBytes(message);
////写入字符串
//filestrem.Write(bytes, 0, bytes.Length);
//Console.ReadKey(); StreamWriter streamwriter = new StreamWriter(filestrem);
streamwriter.WriteLine("我是帅帅的一小时小超人!");
streamwriter.Close(); }
}
}

  从代码可以很明显在看出来,FileStream写入的时候是操作的是byte数组,StreamWrite操作的就是字符串。这就是这两个类的最大区别。

  StreamWrite类操作字符/字符串比较方便,但是有些场景下使用FileStream对象更合适,操作字节都是用FileStream比较合适,StreamRead是同样的道理占时不想详细在说了。

  PS:知识点会都持续补充的,作为本人复习,学习,整理知识用。

三. Directory DirectoryInfo 和File Fileinfo,Path的作用,有什么区别?

  File类和FileInfo类两个的类的功能是差不多,都是操作文件的。可以对文件进行增删该查读写,但是File类是静态类不需要创建,所以他们的不同的应用场景就出现了,如果对文件进行单次操作的话,就用File类就好了。因为File类是静态类不需要创建对象也不需要销毁对象,可以减少性能开销。

  这里不明白的同学可能会和我之前一样疑惑,既然静态类不需要创建对象,比Fileinfo类好那么多。那还要Fileinfo还干嘛?那就直接用File类不就好了。其实不然,因为File类每次调用的时候都要去进行安全检查,占用Cup,File每次都会去寻找文件性能浪费。但是FileInfo类在只会在创建的时候去寻找一次,所以显而易见,对文件进行单步操作的时候,就是操作的一次的时候,适合使用File类。但是进行多次操作的时候,就是FileInfo更适合了,因为FileInfo虽然需要创建对象和销毁,但是减少了每次操作要去寻找文件的消耗。所以这里的适合与否主要是看性能。

  Directory和DirectoryInfo同理。

1.File类和FileInfo类详细介绍介绍。

  File类的常用操作

            //创建一个文件。
File.Create(@"D:\一小时小超人2.txt"); //写入方式1:结合FileStream
FileStream fileStream = File.Create(@"D:\一小时小超人3.txt");//1.创建完了文件。往文件写入东西。File.Create返回的是一个FileStream对象。FileStream对象可以支持往文件写入字节。
string sfilecontent = "我是帅帅的小超人"; //2.这就是上面FileStream的知识点,写入byte数组。
byte[] bytes1 = Encoding.UTF8.GetBytes(sfilecontent);//3.将字符串转换为字节写入,因为我上面的说到,FileStream和StreamWrite都可以进行写入操作,最大的区别就是FileStream操作的是字节,Stream操作的是字符串。
fileStream.Write(bytes1, 0, bytes1.Length); //写入方式2:集合StreamWriter
StreamWriter streamwrite = File.CreateText(@"D:\一小时小超人4.txt");
streamwrite.Write("我是帅帅的小超人");
streamwrite.Close(); //写入方式3:File本身就支持写入
string sfilecontent1 = "我是酷酷的一小时小超人";
File.WriteAllText(@"D:\一小时小超人3.txt", sfilecontent1);//注意这个操作比较适合对已经存在文件进行读写。如果文件不存在。根据我们前面讲的File和FileInfo的区别这个地方我们应该用FileInfo
//File.WriteAllBytes();写入字节
//File.WriteAllLines();一行一行写

  上面的代码演示的File类的创建写入,演示了两种方式,FileStream的写入字节数组,StreamWriter写入的是字符串。

            //读取方式1:结合FileStream
string txt = string.Empty;
FileStream fs = File.OpenRead(@"D:\一小时小超人3.txt");
byte[] bytes2 = new byte[1024];
while (fs.Read(bytes2, 0, bytes2.Length) > 0)
{
txt += Encoding.UTF8.GetString(bytes2); }
Console.WriteLine(txt);
Console.ReadKey(); //读写方式2:集合StreamRead
string txt1 = string.Empty;
StreamReader streamreader=File.OpenText(@"D:\一小时小超人4.txt");
txt1= streamreader.ReadLine();
while (!streamreader.EndOfStream)
{
txt1+= streamreader.ReadLine();
}
Console.WriteLine(txt1);
Console.ReadKey();

  上面的地方演示了File的读取。

  FileInfo类的常用操作

            FileInfo file = new FileInfo(@"D:\一小时小超人1000.txt");
FileStream fileStream = file.Create();//创建文件,文件存在,就重新覆盖。返回FileStream对象进行读写
FileStream fileStream1 = file.OpenRead();//打开文件,如果文件不存在,则会抛出 FileNotFoundException 异常。
FileStream fileStream2 = file.Open(FileMode.OpenOrCreate);//打开文件,但是有一个文件模式枚举的参数可以设置。这里我先设置了FileMode的值是OpenOrCreate,如果不存在就创建,这个方法有多个重载。详细的请看MSDN文档。
StreamWriter streamread = file.CreateText();//创建文件,返回StreamWriter对象进行写入
StreamReader streamread1 = file.OpenText();//创建对象返回StreamReader进行读。
file.Delete();//删除。

Fileinfo类和File功能都是差不多,我简单的在上面代码列举了一下各种语法,并且做了注释。如果刚学习的小伙伴有疑问,或者书写有误,请在下面帮指出来,方便我们讨论,和纠错。

C#知识点:I/O的更多相关文章

  1. ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

  2. ASP.NET MVC开发:Web项目开发必备知识点

    最近加班加点完成一个Web项目,使用Asp.net MVC开发.很久以前接触的Asp.net开发还是Aspx形式,什么Razor引擎,什么MVC还是这次开发才明白,可以算是新手. 对新手而言,那进行A ...

  3. UWP开发必备以及常用知识点总结

    一直在学UWP,一直在写Code,自己到达了什么水平?还有多少东西需要学习才能独挡一面?我想对刚接触UWP的开发者都有这种困惑,偶尔停下来总结分析一下还是很有收获的! 以下内容是自己开发中经常遇到的一 ...

  4. C#高级知识点&(ABP框架理论学习高级篇)——白金版

    前言摘要 很早以前就有要写ABP高级系列教程的计划了,但是迟迟到现在这个高级理论系列才和大家见面.其实这篇博客很早就着手写了,只是楼主一直写写停停.看看下图,就知道这篇博客的生产日期了,谁知它的出厂日 ...

  5. lucene 基础知识点

    部分知识点的梳理,参考<lucene实战>及网络资料 1.基本概念 lucence 可以认为分为两大组件: 1)索引组件 a.内容获取:即将原始的内容材料,可以是数据库.网站(爬虫).文本 ...

  6. DoraCMS 源码知识点备注

    项目需要研究了下DoraCMS这款开源CMS,真心做的不错:).用的框架是常用的express 4 + mongoose,代码也很规范,值得学习. 源码中一些涉及到的小知识点备注下: https:// ...

  7. atitit 商业项目常用模块技术知识点 v3 qc29

    atitit 商业项目常用模块技术知识点 v3 qc29 条码二维码barcodebarcode 条码二维码qrcodeqrcode 条码二维码dm码生成与识别 条码二维码pdf147码 条码二维码z ...

  8. HTML5知识点总结

    HTML5知识点总结(一) 一.HTML新增元素 1.IE9版本以下支持HTML5的方法 <!--[if lt IE9]> <script src="http://cdn. ...

  9. JavaScript易错知识点整理

    前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一 ...

  10. Sqlserver中一直在用又经常被忽略的知识点一

    已经有快2个月没有更新博客了,实在是因为最近发生了太多的事情,辞了工作,在湘雅医院待了一个多月,然后又新换了工作...... 在平时的工作中,Sqlserver中许多知识点是经常用到的,但是有时候我们 ...

随机推荐

  1. Java高级篇反射和注解

    反射是什么? 反射的作用?能带来什么好处? 反射的使用? 注解的使用? 注解和反射配合实战...

  2. 从零搭建Spring Boot脚手架(3):集成mybatis

    1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文集成了一些基础的功能,比如统一返回体.统一异常处理.快速类型转换.参数校验等常用必备功能,并编写了一些单元测试进行验证,今天 ...

  3. Java基础—继承

    继承是面向对象的核心特征之一,是由已有类创建新类的机制.利用继承机制,可以先创建一个具有共性的一般类,然后根据该一般类创建具有特殊性的新类,新类继承一般类的属性和方法,并根据需要增加自己的新属性和方法 ...

  4. 《Java核心技术(卷1)》笔记:第12章 并发

    线程 (P 552)多进程和多线程的本质区别:每一个进程都拥有自己的一整套变量,而线程共享数据 (P 555)线程具有6种状态: New(新建):使用new操作符创建线程时 Runnable(可运行) ...

  5. Java Redis系列1 关系型数据库与非关系型数据库的优缺点及概念

    Java Redis系列1 关系型数据库与非关系型数据库的优缺点及概念 在学习redis之前我们先来学习两个概念,即什么是关系型数据库什么是非关系型数据库,二者的区别是什么,二者的关系又是什么? ** ...

  6. Vue视图渲染原理解析,从构建VNode到生成真实节点树

    前言 在 Vue 核心中除了响应式原理外,视图渲染也是重中之重.我们都知道每次更新数据,都会走视图渲染的逻辑,而这当中牵扯的逻辑也是十分繁琐. 本文主要解析的是初始化视图渲染流程,你将会了解到从挂载组 ...

  7. 2020-04-13:怎么在日志里排查错误,该用哪些Linux命令

    能通过less命令打开文件,通过Shift+G到达文件底部,再通过?+关键字的方式来根据关键来搜索信息. 能通过grep的方式查关键字,具体用法是, grep 关键字 文件名,如果要两次在结果里查找的 ...

  8. C#LeetCode刷题之#892-三维形体的表面积(Surface Area of 3D Shapes)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4136 访问. 在 N * N 的网格上,我们放置一些 1 * 1 ...

  9. C#LeetCode刷题之#532-数组中的K-diff数对(K-diff Pairs in an Array)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3716 访问. 给定一个整数数组和一个整数 k, 你需要在数组里找 ...

  10. git日常使用的常用命令总结

    git日常使用的常用命令总结 git 是什么? Git是目前世界上最先进的分布式版本控制系统(没有之一). Git(读音为/gɪt/.)是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常 ...