C# 温故而知新:Stream篇(二)
TextReader 和StreamReader
目录:
为什么要介绍 TextReader?
首先让我们来理解下什么是TextReader,从字面上的意思入手的话,大家就会恍然大悟了
一个对于Text的读取器,可是又是怎么读取的呢?聪明的你肯定会想到,当然是通过连续
的字符进行读取, 为什么在介绍StreamReader之前,要搞这个东东? 答案其实很简单:他们
两个就是父子关系,要了解StreamReader最好先了解他的父亲,请允许我对他们进行下简单介绍:
TextReader的常用属性和方法:
我们闭上眼可以想象一下 Text这个词的范围,它囊括了许多的文件类型,我们可以在记事本上
使用任何语言(英语,中文,c# ,天书,javascript,jquery,xml,xaml,sql,c++……),如此多
的语言文本归根结底还是通过一个个char组成的,所以微软构造出了TextReader这个抽象类对于
读取text的一系列操作,同样对于TextReader我们无法直接实例化,应为它是个抽象类,只有
定义类的行为,不针对特定实现。那好吧,看看 TextReader定义了哪些类的行为:
1:具有一个protected类型的构造函数
*2: void Close()方法:和上篇Stream一样,TextReader也有Close方法,我们必须牢记,
在用完之后应该主动关闭它
*3: void Dispose()方法:释放所有该TextReader 所持有的所有资源(注意,假如TextReader中持有stream或其他
对象,当TextReader执行了Dispose方法时,stream对象也被回收了)
*4:int Peek()方法
这个方法主要是寻找当前char的下个 char,当返回值是-1时,表示下个 char已经是最后一个位置的char了
*5:int Read()方法:
同样,read()方法是读取下一个char, 但是和peek方法不同,read()方法使指针指向下个字符,但是peek
还是指向原来那个字符
*6:int Read(Char[] buffer,int index,int count)方法:
这个重载read方法和上一章Stream的read方法有点神似,区别是一个参数是byte数组,而这个是char数组,
(注意:是通过reader 将数据数据读入buffer数组),index:从哪个位置开始,count:读取char数量
*7: int ReadBlock(Char[] buffer,int index,int count)方法:
和Read方法基本一致,区别是从效率上来说ReadBlock更高点,而且ReadBlock并非属于线程安全,使用时要注意
*8:virtual string ReadLine() 方法:
顾名思义,这个方法将读取每一行的数据并返回当前行的字符的字符串
*9:virtual string ReadToEnd()方法:
包含从当前位置到 TextReader 的结尾的所有字符的字符串
下面的例子将是对上述方法的温故而知新:

string text = "abc\nabc";
using (TextReader reader = new StringReader(text)) { while (reader.Peek() != -) { Console.WriteLine("Peek = {0}", (char)reader.Peek()); Console.WriteLine("Read = {0}", (char)reader.Read()); } reader.Close(); }
using (TextReader reader = new StringReader(text)) { char[] charBuffer = new char[]; int data = reader.ReadBlock(charBuffer, , ); for (int i = ; i < charBuffer.Length; i++) { Console.WriteLine("通过readBlock读出的数据:{0}", charBuffer[i]); } reader.Close(); }
using (TextReader reader = new StringReader(text)) { string lineData = reader.ReadLine(); Console.WriteLine("第一行的数据为:{0}", lineData); reader.Close(); }
using (TextReader reader = new StringReader(text)) { string allData = reader.ReadToEnd(); Console.WriteLine("全部的数据为:{0}", allData); reader.Close(); }
Console.ReadLine();

输出结果:

StreamReader登场
终于今天的主角登场了,在前面做了那么多铺垫后在学习它会事半功倍
从StreamReader想到多态
在说明StreamReader之前还有一件事要提起,那就是多态, 多态到底是什么概念呢?聪明的你肯定会想到多态不就是子类的多种
表现形式?不错,但这还是不是完全的,不仅如此,现实世界中,父亲帮儿子买了套房子,但是他没有在房产证上写儿子的名字,
所以这个房子儿子和父亲能共同使用,儿子能根据自己的爱好装修房子,父亲也能住在儿子装修好的房子内,也就是说父类能够
灵活使用子类的功能,更科学的一点就是子类的指针允许(赋值给)父类指针。上述例子中
TextReader reader = new StringReader(text)
这个就是个多态的经典例子大家不妨深刻理解下这个重要的概念
简单介绍下Encoding编码
为什么要简单介绍Encoding编码?因为Encoding编码在Stream和相关类中起的非常重要的作用,
由于Encoding类会在后续章节详细解释,现在我就先介绍下 Encoding类一些重要编码

以上便是Encoding类中一些特定的编码,大家先了解即可,但使用Default时有点必须注意,如果你用不一样编码的机器的时候,
注意服务器或者其他操作系统的编码规则,举个例子,如果你在一个中文操作系统进行编码,但是发布到了一个其他语言的操作
系统上那就会出问题了这时候你必须选择一个通用编码
StreamReader 类的定义和作用
StreamReader 的定义:实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。
在对于流的操作中,StreamReader对于流的读取方面非常重要,为什么这么说呢,我们常用的文件的复制,移动,上传,下载,压缩,保存,
远程FTP文件的读取,甚至于HttpResponse等等只要是于流相关的任何派生类StreamReader 都能够轻松处理,当然,大家甚至可以自定义
相关的派生类去实现复杂的序列化。在实际项目,我们可能碰到过许多上述的情况,有时乱码的问题会让我们发狂,但是只要深刻去理解基础的话,
我相信大家都能找到适合自己的解决方法
StreamReader 类的常用属性及方法
其实StreamReader的一些方法已经在其父类TextReader中说的很仔细了,但是个人觉得构造函数和属性才是重点.
首先上构造函数:
*1: StreamReader(Stream stream)
将stream作为一个参数 放入StreamReader,这样的话StreamReader可以对该stream进行读取操作,Stream对象可以非常广泛,包括所有Stream的派生类对象
*2: StreamReader(string string, Encoding encoding)
这里的string对象不是简单的字符串而是具体文件的地址,然后根据用户选择编码去读取流中的数据
*3: StreamReader(string string,bool detectEncodingFromByteOrderMarks)
有时候我们希望程序自动判断用何种编码去读取,这时候detectEncodingFromByteOrderMarks这个参数就能起作用了,当设置为true的 时候数通过查看流的前三个字节
来检测编码。如果文件以适当的字节顺序标记开头,该参数自动识别 UTF-8、Little-Endian Unicode 和 Big-Endian Unicode 文本,当为false 时,方法会去使用用户提供
的编码
*4: StreamReader(string string, Encoding encoding, bool detectEncodingFromByteOrderMarks,int bufferSize)
这个放提供了4个参数的重载,前3个我们都已经了解,最后个是缓冲区大小的设置,
*StreamReader 还有其他的一些构造函数,都是上述4个的扩充,所以本例就取上述的4个构造函数来说明
属性:
1:BaseStream
大家对于前一章流的操作应该没什么问题,我就直切主题,最简单的理解就是将上述构造函数的流对象在重新取出来进行一系列的操作,
可是如果构造函数中是路径怎么办,一样,构造函数能够将路径文件转化成流对象
FileStream fs = new FileStream ( "D:\\TextReader.txt", FileMode.Open , FileAccess.Read ) ; StreamReader sr= new StreamReader ( fs ) ;
//本例中的BaseStream就是FileStream sr.BaseStream.Seek ( , SeekOrigin.Begin ) ;
2:CurrentEncoding:
获取当前StreamReader的Encoding
3:EndOfStream:
判断StreamReader是否已经处于当前流的末尾
最后用FileStream的示例来温故下StreamReader

static void Main(string[] args)         {                         //文件地址            string txtFilePath="D:\\TextReader.txt";             //定义char数组            char[] charBuffer2 = new char[];
            //利用FileStream类将文件文本数据变成流然后放入StreamReader构造函数中            using(FileStream stream = File.OpenRead(txtFilePath))             {                 using (StreamReader reader = new StreamReader(stream))                 {                     //StreamReader.Read()方法                    DisplayResultStringByUsingRead(reader);                 }             }
            using (FileStream stream = File.OpenRead(txtFilePath))             {                 //使用Encoding.ASCII来尝试下                using (StreamReader reader = new StreamReader(stream,Encoding.ASCII,false))                 {                     //StreamReader.ReadBlock()方法                    DisplayResultStringByUsingReadBlock(reader);                 }             }
            //尝试用文件定位直接得到StreamReader,顺便使用 Encoding.Default            using(StreamReader reader = new StreamReader(txtFilePath, Encoding.Default,false,))             {                //StreamReader.ReadLine()方法              DisplayResultStringByUsingReadLine(reader);             }
            //也可以通过File.OpenText方法直接获取到StreamReader对象            using (StreamReader reader = File.OpenText(txtFilePath))              {                 //StreamReader.ReadLine()方法                DisplayResultStringByUsingReadLine(reader);             }
            Console.ReadLine();         }
        /// <summary>/// 使用StreamReader.Read()方法         /// </summary>/// <param name="reader"></param>        public static  void DisplayResultStringByUsingRead(StreamReader reader)          {             int readChar = ;             string result = string.Empty;             while ((readChar=reader.Read()) != -)              {                 result += (char)readChar;             }             Console.WriteLine("使用StreamReader.Read()方法得到Text文件中的数据为 : {0}", result);         }
        /// <summary>/// 使用StreamReader.ReadBlock()方法         /// </summary>/// <param name="reader"></param>        public static void DisplayResultStringByUsingReadBlock(StreamReader reader)         {             char[] charBuffer = new char[];             string result = string.Empty;             reader.ReadBlock(charBuffer,,);             for (int i = ; i < charBuffer.Length; i++)             {                 result += charBuffer[i];             }             Console.WriteLine("使用StreamReader.ReadBlock()方法得到Text文件中前10个数据为 : {0}", result);         }
         /// <summary>/// 使用StreamReader.ReadLine()方法         /// </summary>/// <param name="reader"></param>        public static void DisplayResultStringByUsingReadLine(StreamReader reader)         {             int i=;             string resultString = string.Empty;             while ((resultString=reader.ReadLine() )!= null)             {                 Console.WriteLine("使用StreamReader.Read()方法得到Text文件中第{1}行的数据为 : {0}", resultString, i);                 i++;             }                      }

输出结果:

本章总结
本章详细介绍了TextReader和StreamReader的定义概念和一些注意事项,希望大家能够在本文中温故而知新,下章会简单介绍下TextWriter和StreamWriter
C# 温故而知新:Stream篇(二)的更多相关文章
- C# 温故而知新:Stream篇(—)
		C# 温故而知新:Stream篇(—) 目录: 什么是Stream? 什么是字节序列? Stream的构造函数 Stream的重要属性及方法 Stream的示例 Stream异步读写 Stream 和 ... 
- 【基于WinForm+Access局域网共享数据库的项目总结】之篇二:WinForm开发扇形图统计和Excel数据导出
		篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ... 
- 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇二:基于OneNote难点突破和批量识别
		篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ... 
- 《高性能javascript》 领悟随笔之-------DOM编程篇(二)
		<高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ... 
- SQL Server调优系列玩转篇二(如何利用汇聚联合提示(Hint)引导语句运行)
		前言 上一篇我们分析了查询Hint的用法,作为调优系列的最后一个玩转模块的第一篇.有兴趣的可以点击查看:SQL Server调优系列玩转篇(如何利用查询提示(Hint)引导语句运行) 本篇继续玩转模块 ... 
- php基础篇-二维数组排序 array_multisort
		原文:php基础篇-二维数组排序 array_multisort 对2维数组或者多维数组排序是常见的问题,在php中我们有个专门的多维数组排序函数,下面简单介绍下: array_multisort(a ... 
- C蛮的全栈之路-node篇(二) 实战一:自动发博客
		目录 C蛮的全栈之路-序章 技术栈选择与全栈工程师C蛮的全栈之路-node篇(一) 环境布置C蛮的全栈之路-node篇(二) 实战一:自动发博客 ---------------- 我是分割线 ---- ... 
- 【SSRS】入门篇(二) -- 建立数据源
		原文:[SSRS]入门篇(二) -- 建立数据源 通过 [SSRS]入门篇(一) -- 创建SSRS项目 这篇,我们建立了一个SSRS项目: 接下来,我们以 AdventureWorks2012 示例 ... 
- 【转】java提高篇(二)-----理解java的三大特性之继承
		[转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in ja ... 
- CYQ.Data 轻量数据层之路 使用篇二曲 MAction 数据查询(十三)----002
		原文链接:https://blog.csdn.net/cyq1162/article/details/53303390 前言说明: 本篇继续上一篇内容,本节介绍所有相关查询的使用. 主要内容提要: 1 ... 
随机推荐
- [转]编写Android.mk中的LOCAL_SRC_FILES的终极技巧
			希望看原文的请移步:[原创]编写Android.mk中的LOCAL_SRC_FILES的终极技巧 问题的引入 在使用NDK编译C/C++项目的过程中,免不了要编写Android.mk文件,其中最重要的 ... 
- qt中 中文乱码问题
			qt是跨平台的开发平台.他的编译器是要手动配置的,在window下一般我们用virtual stuido中cl,或者Mingw中的g++ 在linux中一般采用Linux下的g++ 而 微软VS的中 ... 
- 0058 Spring MVC如何向视图传值--Model--ModelMap--ModelAndView--@ModelAttribute
			MVC,模型.视图.控制器,请求来了,控制器负责找到Controller进行一通计算,计算的结果放到模型里,再找视图把结果呈现出来. 请求里一般都包含了一些参数,前面说了,Spring MVC有很多种 ... 
- URLConnection格式与用法
			private void getdialog() { final EditText et = new EditText(this); final String workid = this.workid ... 
- spring session实现集群中session共享
			本文转自:http://dorole.com/1422/ 使用框架的会话管理工具,也就是本文要说的spring-session,可以理解是替换了Servlet那一套会话管理,既不依赖容器,又不需要改动 ... 
- 【Unity笔记】UGUI物体的Rect Transform组件(Pivot中心点,Anchor锚点)
			Pivot:自身中心点,图标是小蓝点.表示图片以哪个点来计算坐标值.默认在UI元素的几何中心点(0.5, 0,5). Anchor:锚点,图标是四个小三角形.表示该UI元素以父物体的哪个位置作为缩放参 ... 
- 【C#学习笔记】反射的简单用法
			常见的使用反射的场景: 程序在运行时动态地访问类的成员,如获得类的变量.方法. 例如:用反射给本类的变量赋值. public class Student{ public string studentN ... 
- vue点击返回顶部插件vue-totop
			vue-totop vue 点击返回顶部插件,可以根据参数设定按钮大小,颜色,类型,返回顶部的时间等.github地址:https://github.com/1006008051/vue-totop, ... 
- iOS边练边学--触摸事件以及能够拖拽的UIView的练习
			一.用户在使用APP的过程中,会产生各种各样的事件.iOS中的事件可以分为3大类型: 二.响应者对象 在iOS中只有继承了了UIResponder的对象才能接受并处理事件,这样的对象称之为“响应者对象 ... 
- WPF教程六:布局之Grid面板
			Grid:网格面板 Grid顾名思义就是“网格”,以表格形式布局元素,对于整个面板上的元素进行布局,它的子控件被放在一个一个事先定义好的小格子里面,整齐配列. Grid和其他各个Panel比较起来,功 ... 
