C# 文件读写系列三

1、读写文本文件

C# 文件读写系列二中列举了相当多的读写文本文件的方法,大致有以下几种:

(1)、通过静态类File的静态方法来进行文本文件的读写,主要有ReadAllBytes()、ReadAllLines()、ReadAllText()、WriteAllBytes()、WriteAllLines()、WriteAllText().

(2)、通过FileStream的实例方法,主要有Read()、Write()

本文将介绍两个级别更加高的类来完成文本文件的读写.==========>StreamReader和StreamWriter

2、StreamReader和StreamWriter简介

C# 文件读写系列二中,我使用了FileStream完成了读取和写入文本文件的功能,但是FileStream并不是完成读写文本文件最好的类,通常某个特殊文件如果包含文本内容,使用StreamReader和StreamWriter可以更好的读写它们,而不是使用FileStream,因为前者的级别更高,特别适合于读写文本文件,StreamReader和StreamWriter相对与FileStream的优势在于以下几点:

(1)、FileStream是一个比较底层的类,只能简单的读文件到缓冲区,而StreamReader和StreamWriter的实例方法ReadLine()、WriteLine()。ReadLine()可以根据流的内容,自动检测出停止读取文本方便的位置。WriteLine()在写入文件时,流会自动把回车符和换行符追加到文本的末尾.而FileStream则需要自己处理.

(2)、使用StreamReader和StreamWriter不需要考虑(文本格式)文件的编码方式,因为windows所有的文本文件除了ASCII编码的文件,它只包含文本,如果文件是Uniocde格式,这就使用文件的前两个或者前三个字节来表示,这些字节称为字节码标记.例如在使用windows程序,如Notepad或者WordPad打开一个文件时,则不需要考虑文件的编码问题,因为应用程序会自动识别所打开文件的编码.StreamReader类也是一样,它能自动读取任何格式的文件,而StreamWriter类可以使用任何一种编码技术来格式化要输出的内容,但是如果使用FileStream类读取和显示文本,就必须自己来处理这个过程.

(3)、StreamReader和StreamWriter操作都是字符数据(char),而FileStream操作的是字节数据(byte),他们的默认编码都是UTF-8,而一个中文占两个字符

(4)、StreamXXX类常用于文本的打开与保存,FileStream则用于数据的传输.

(5)、FileStream不能指定编码(因为他看到的是文件的二进制形式,当然无所谓编码),所以如果有中文的话需要转码.

但是FileStream也有它自己的优势,FileStream可以指定FileMode、FileAccess、FileShare、FileOptions等各种控制,扩大了文件读写的灵活性,FileStream还提供了BeginRead/BeginWrite(异步读写)的操作方法,所以FileStream用的好的话,效率还是非常高的.

3、StreamReader

使用StreamReader读取文本文件比使用FileStream读取文本文件更加的简单,方便。因为构造一个StreamReader实例来读取文本文件比使用FileStream更加的容易,因为使用StreamReader不需要FileStream的FileMode、FileAcess、FileShare等参数,因为StreamReader只能进行读取操作.StreamReader的构造函数参数主要有以下两个:

(1)、指定文件的编码方式,通过Encoding类

(2)、在没有提供要读取的文件名的情况下,为StreamReader提供了一个Stream流,可以是FileStream、MemoryStream、BufferedStream。因为StreamReader级别很高,所以当有另一个流在读取其他源中的数据,如通过FileStream读取一个文件,所生成的文件流,需要通过StreamReader提供的工具来处理,那么就可以把FileStream的输出流传递给StreamReader,这样StreamReader就可以处理任何数据源(不仅仅是文本文件)中的数据.

(3)、StreamReader共有13个构造函数,下面来一一使用

第一个:提供一个Stream实例(流实例),可以是FileStream、MemoryStream、BufferedStream

FileStream fs = new FileStream(@"C:\Users\Administrator\Desktop\test.txt",FileMode.Open);
StreamReader sr = new StreamReader(fs);

第二个:提供文件的路径

StreamReader sr = new StreamReader(@"C:\Users\Administrator\Desktop\test.txt");

第三个:提供流实例,并设置该流是否需要带字节码标记检测选项。  

StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"),true);

第四个:提供流实例,并设置指定的字符编码

StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"),Encoding.GetEncoding(936));

注:936是Gb2312的代码页.

第五个:提供流实例,并设置指定的字符编码,并设置该流是否需要带字节码标记检测选项。  

StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"),Encoding.GetEncoding(936),true);

第六个:提供流实例,并设置指定的字符编码,并设置该流是否需要带字节码标记检测选项,并设置最小缓冲区大小.

StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"),Encoding.GetEncoding(936),true,512);

剩下的都是路径的重载,这里就不过多介绍.

(4)、StreamReader常用方法

第一个: Read(),该方法是一个虚方法,其作用是读取输入流中的下一个字符,并使该字符的位置提升一个。

返回值:字符的十进制

代码如下:

//使用gb2312对文件进行转码,否则会出现乱码
StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"),Encoding.GetEncoding(936));
int valToRead = 0;
while ((valToRead=sr.Read()) != -1)
{
    Console.WriteLine(Convert.ToChar(valToRead));//将int型转换成ASCII字符
}

Read()方法的重载Read(char[] buffer,int index,int count)

返回值:读取的字符总数

代码如下:

//使用gb2312对文件进行转码,否则会出现乱码
StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"),Encoding.GetEncoding(936));
char[] buffer = new char[7];
int readCount = sr.Read(buffer,0,6);//最多读取7个字符到buffer数组中
for (int i = 0; i <readCount; i++)
{
      Console.WriteLine(buffer[i].ToString());
}  
sr.Read();

第二个:ReadLine(),行读入。从当前流读取一行数据,并作为字符串返回,如果读到下一行没有数据,则返回null。代码如下:

//使用gb2312对文件进行转码,否则会出现乱码
StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"), Encoding.GetEncoding(936));
string strLine=null;
while ((strLine = sr.ReadLine()) != null)
{
     Console.WriteLine(strLine);
}

第三个:ReadToEnd(),从流的当前位置读到流的末尾位置,将文件流一次性全部加载到内存中

注:内存中的数据操作是极快的,但是如果文件过大的话,可能内存就会不够,需要采用Read()或ReadLine()进行读取.代码如下:

//使用gb2312对文件进行转码,否则会出现乱码
StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"), Encoding.GetEncoding(936));
string content=sr.ReadToEnd();
Console.WriteLine(content);

第四个:Peek(),读取下一个字符,但位置不移动

//使用gb2312对文件进行转码,否则会出现乱码
StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"), Encoding.GetEncoding(936));
while (sr.Peek() != -1)
{
      Console.WriteLine(sr.ReadLine());
}

 (5)、StreamReader属性

第一个:EndOfStream,判断当前读取流的位置是否在末尾,代码如下:

//使用gb2312对文件进行转码,否则会出现乱码
StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"), Encoding.GetEncoding(936));
while (!sr.EndOfStream)
{
      Console.WriteLine(sr.ReadLine());
}

第二个:CurrentEncoding,获取当前流的编码,代码如下:

//使用gb2312对文件进行转码,否则会出现乱码
StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"), Encoding.GetEncoding(936));
Console.WriteLine(sr.CurrentEncoding);

第三个:BaseStream,返回基础流

StreamReader sr = new StreamReader(File.OpenRead(@"C:\Users\Administrator\Desktop\test.txt"), Encoding.GetEncoding(936)); 
Console.WriteLine(sr.BaseStream);

4、StreamWriter

注:当使用StreamWriter写入数据的时候,除非显示的调用Flush或者Close方法,或者设置AutoFlush的值为true,否则其缓冲区将不会刷新到基础流,也就是数据不会写入到硬盘中.

和StreamReader一样,相比FileStream构造一个StreamWriter要容易的多,不需要FileMode、FileAccess、FileShare等参数.

主要的构造参数和StreamReader一样,一个Encoding和一个Stream实例.下面主要介绍StreamWriter的构造函数.

(1)、StreamWriter构造函数.

第一个:提供一个Stream实例(流实例),可以是FileStream、MemoryStream、BufferedStream

FileStream fs=new FileStream(@"C:\Users\Administrator\Desktop\test.txt",FileMode.CreateNew);
StreamWriter sw=new StreamWriter(fs);

(2)、提供一个Stream实例(流实例),可以是FileStream、MemoryStream、BufferedStream,并设置流的编码

FileStream fs=new FileStream(@"C:\Users\Administrator\Desktop\test.txt",FileMode.CreateNew);
StreamWriter sw = new StreamWriter(fs, Encoding.GetEncoding(936));

(3)、提供一个Stream实例(流实例),可以是FileStream、MemoryStream、BufferedStream,并设置流的编码,并设置缓冲区大小。

FileStream fs=new FileStream(@"C:\Users\Administrator\Desktop\test1.txt",FileMode.CreateNew);
StreamWriter sw = new StreamWriter(fs, Encoding.GetEncoding(936),6);

(4)、提供一个Stream实例(流实例),可以是FileStream、MemoryStream、BufferedStream,并设置流的编码,并设置缓冲区大小,在释放writer之后,是否打开流对象.

FileStream fs=new FileStream(@"C:\Users\Administrator\Desktop\test1.txt",FileMode.Create);
StreamWriter sw = new StreamWriter(fs,Encoding.UTF8,2,false);
sw.Write("aaa");
sw.Dispose();//释放sw 
Console.WriteLine(fs.CanWrite);

 参数换成true,输出就为true,自行验证.

也就是说,当前leaveOpen参数设置true时,当释放了sw,fs仍然可以方法,反之,则不能访问,因为在释放sw的同时,fs也被关闭了.

剩下的构造函数都是关于string path的重载,这里就不多介绍了.

(2)、StreamWriter的常用方法

第一个:Write(),该方法就不多做介绍,都是一些比较简单的重载.

第二个:WriteLine(),写入一个空行,并跳转到下一行,代码如下:

FileStream fs=new FileStream(@"C:\Users\Administrator\Desktop\test1.txt",FileMode.Create);
StreamWriter sw = new StreamWriter(fs,Encoding.UTF8,2,true);
sw.Write("a");
sw.WriteLine();
sw.WriteLine();
sw.Write("b");
sw.Close();

关于其他的WriteLine()的重载,这里也不多做解释,都是一些比较简单的重载.

第三个:Flush()

(3)StreamWriter的常用属性

AutoFlush:设置StreamWriter 是否在每次调用 StreamWriter.Write 之后,将其缓冲区刷新到基础流。也就是将数据写入到硬盘.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Albert陈凯

2018-10-24 Oracle中insert into select和select into的用法

在Oracle中select into from不可以使用-----原因很简单:select into是PL/SQL language 的赋值语句!如果使用则O...

851
来自专栏用户2442861的专栏

初学Redis(2)——用Redis作为Mysql数据库的缓存

http://blog.csdn.net/qtyl1988/article/details/39519951

1842
来自专栏Greenplum

Greenplum 对JSON的支持

源文章:http://www.postgresqltutorial.com/postgresql-json/

841
来自专栏IMWeb前端团队

bash 的条件和循环

本文作者:IMWeb 江源 原文出处:IMWeb社区 未经同意,禁止转载 原文 条件语句和循环可以统称为流程控制,是一门语言最基础的部分。 bash ...

1916
来自专栏*坤的Blog

自写文件小工具类

1793
来自专栏技术博客

Entity Framework DataAnnotations

DataAnnotation 特性由.NET 3.5中引进,给.NET中的类提供了一种添加验证的方式。但是在EF中它又可以对映射关系进行控制,相比较Fluent...

973
来自专栏PHP在线

mysql学习笔记

InnoDB引擎与MyISAM引擎 mysql是关系型数据库。其中的存储引擎可以show engines来查看。我的版本是5.6.26的,查看版本用selec...

2895
来自专栏程序员叨叨叨

【PHP】Propel的使用,看这一篇就够了

本文为学习Propel框架使用的笔记,默认已经安装好Propel环境,若有读者不知如何安装Propel,可参考《听说你PHP配置Composer遇到了一些困境》...

4445
来自专栏java学习

Java每日一练(2017/8/2)

本期题目: (单选题)1、在 java 中,一个类可同时定义为许多同名的方法,这些方法的形式参数个数,类型或顺序各不相同,传回的值可能个不相同,这种面向对象的...

2917
来自专栏xingoo, 一个梦想做发明家的程序员

AngularJS API之toJson 对象转为JSON

toJson()能把对象序列化为json 方法讲解 这个方法最多支持2个参数: angular.toJson(obj, pretty); obj 是想要转换的...

2525

扫码关注云+社区

领取腾讯云代金券