StreamReader继承于抽象类TextReader,是用来进行文本文件字符流读的类。
它是按照一种特定的编码从字节流中读取字符,其常用的构造函数如下:
public StreamReader (String path)
以默认的编码方式对字符进行读取,这里的默认的编码方式是UTF-8.因此,以这种编码方式读取有简体中文的时候,会出现乱码。这种读取方式仅限于读取一般的UTF-8字符。如果要能正确显示读取的简体中文,应该要使用Encoding.Default的编码方式,它是标准的GB2312简体中文,由下面的构造函数来完成:
public StreamReader (String path,Encoding encoding)
这里的Encoding便是字符编码的方式,常见的有ASCII,UTF-8,UTF-7,Unicode等方式。
StreamReader类的几个重要的方法是:Read(),ReadLine(),ReadToEnd(),Peek(),下面逐一介绍。
Read()方法的作用是读取一个或者几个字符,它有两个重载的函数:
public override int Read ()
用来在文本文件中读取一个字符,读完一个字符后,文件的指针往后推进一位,注意它的返回值其实是Int32,不是字符型的,当读取的值是-1时表示到了文件的末尾了。请看下面的程序:
using System;
using System.IO;
using System.Text;
class Test
{
public static void Main()
{
try
{
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
int s,t=0;
while ((s=sr.Read())!=-1)
{
Console.WriteLine("{0}\n",Convert.ToChar(s));
t++;
}
Console.WriteLine(t);
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
}
在bin文件夹下建立一个TestFile.txt,向里面写两行字母:
abc
def
执行的结果是,一共有8个字符,这是因为“回车换行”作为两个字符"\r\n"出现在了文本中。
Read()方法的另一个重载的函数是:
public override int Read (
[InAttribute] [OutAttribute] char[] buffer,
int index,
int count
)
它是指,从文件中读取一定数目的字符到数据缓存器中。buffer是数据缓存器,index是值在buffer中存放的起始位置,count是数目,返回值表示正常读取的字符的个数,肯定是小于等于count的,可以看下面的程序进行理解:
using System;
using System.IO;
using System.Text;
class Test
{
public static void Main()
{
try
{
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
char[] Buffer = new char[10];
Console.WriteLine(sr.Read(Buffer, 0, 10));
Console.WriteLine("读取内容:");
for (int i = 0; i < 10;i++ )
{
Console.WriteLine(Buffer[i]);
}
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
}
在这里,TestFile.txt和上面的例子中时一样的,可以看得出来,虽然在Read中写了10个字符,而实际文件中只有8个字符,所以返回值是8,它也会改变文件流中的位置。
下面介绍ReadLine方法,
public override string ReadLine ()
从当前流中读取一行字符,并将数据作为字符串返回。如果到了文件的末尾,则返回null。
同样对于TestFile.txt,用下面的代码进行理解:、
using System;
using System.IO;
using System.Text;
class Test
{
public static void Main()
{
try
{
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
String line;
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
}
接下来继续,讲解ReadToEnd,它是把从文件的当前位置到文件的末尾的字符全部读出,然后存储到一个string中,参加下面的代码:
using System;
using System.IO;
using System.Text;
class Test
{
public static void Main()
{
try
{
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
sr.Read();
string rest = sr.ReadToEnd();
Console.WriteLine(rest);
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
}
紧接着说说Peek().它返回下一个可用的字符,但是文件流的当前位置不变,区别于Read()在于,文件的字符流的当前位置是否改变。
public override int Peek ()
具体的理解,参加下面的代码:
using System;
using System.IO;
using System.Text;
class Test
{
public static void Main()
{
try
{
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
Console.WriteLine(Convert.ToChar(sr.Peek()));
string rest = sr.ReadToEnd();
Console.WriteLine(rest);
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
}
尽管已经执行了Peek(),但是使用ReadToEnd方法时,依旧能把所有的字符输出,这充分表明,Peek不改变文件流中的数据指针。