C#学习笔记 文本输入/输出

使用Reader和Writer的文本I/O

TextWriter类和TextReader类是基于文本的抽象类,它们的重要子类包括:StreamWriterStreamReader,处理流的操作;StringWriterStringReader,处理字符串的操作。注意:对于C程序员来说,StreamWriter类似于printf()或者fprintf(),而StringWriter类似于sprintf()

1.TextWriter

TextWriter是一个抽象基类,它包含下面一些子类:

  • ① 用来为浏览器客户端编写HTML的HtmlTextWriter
  • ② 用来向ASP.NET网页中的HTTP响应对象写入文本的HttpWriter
  • ③ 使用缩进控制写入文本的IndentedTextWriter
  • ④ 向流中写入字符的StringWriter
  • ⑤ 向字符串中写入字符的StringWriter

TextWriter有3个属性:Encoding,用来返回产生输出的字符编码;FormatProvider,用来引用对文本进行格式化的对象;NewLine,用来返回当前使用平台上所用的行结束符。
TextWriter类中的方法:

  • Close,关闭TextWriter并释放所有与之相关的资源
  • Dispose,释放与TextWriter相关的资源
  • Flush,将保留在TextWriter缓冲区中的未录入数据写入
  • Synchronized,创建TextWriter对象的一个线程安全包
  • Write,向流中写入数据
  • WriteLine,向流中写入数据并换行

TextWriter的Write()方法是将数据以字符串的方式写出。要注意与其他类相比:StreamWrite()方法写的是字节,BinaryWriterWriter()方法是将基本数据类型以原始的方式写出。
Write()方法可以将object对象写出,它会调用对象的ToString()方法转成字符串。还可以带格式字符串,格式字符串的用法与Console.Write()方法相似,事实上,Console.Write()方法调用的就是TextWriter的方法。
静态的Synchronized()方法可以为TextWriter创建一个线程安全包装来保证其安全性,使得用到同一个TextWriter的两个线程彼此之间不会相互干扰。

2.StreamWriter

StreamWriter是TextWriter的一个子类,用来通过特定的编码方式向流中写入字符。默认的编码方式是UTF-8,该方式适用于操作系统本地版本上的统一编码标准的字符。如果想使用其他的编码方式,可以使用System.Text命名空间所提供的ASCII和UTF-7编码,或者根据System.Text.Encoding创建自己的编码方式。
当构造一个StreamWriter对象时,可以指定一个文件名或者现存的流的名称,并指定一种编码方式。下面的代码片段展示了如何创建一个向文件中写入内容的StreamWriter对象:

	FileStream fs = new FileStream(@"C:\temp\foo.txt", FileMode.Create);
	StreamWriter writer = new StreamWriter(fs);

其中,FileStream对象用来向foo.txt文件中写入内容,StreamWriter对象的作用是把字符转换成字节然后输出到FileStream中去。
StreamWriter有一个AutoFlush属性,该属性为真时,对象美执行一次Write()操作都会刷新缓冲区。这样可以确保输出内容一直是最新的,但这种做法不如允许StreamWriter缓冲其输出内容那样有效。BaseStream属性提供对基本Stream对象的访问。
除了从TextWriter中继承的方法之外,StreamWriter类没有添加任何新方法,但重载了用于向流中写入字符和字符串的Write()方法。

3.StringWriter方法

StringWriter用来将其输出内容写入到一个字符串中。由于被写入的字符串处于被修改状态,因此输出内容实际上是被写入StringBuilder,而不是被写入到String中,因为String是不可以被改变的。
StringWriter拥有一套Write()方法,以及GetStringBuiler()ToString()方法,用来处理字符串创建中的缓冲器。
下面代码展示了如何创建和使用StringWriter

	StringWriter sw = new StringWriter();
	int n = 42;
	sw.Write("The value of n is {0}", n);
	sw.Write("... and some more characters");
	Console.WriteLine(sw.ToString());

4.TextReader

TextReader类用于读取字符串。TextReader类有两个子类StreamReaderStringReader。该类中包含的方法比TextWriter类要少,但其处理方式是一样的:

  • Close,关闭TextReader并释放所有与之相关的资源
  • Peek,浏览下一字符,但不将其从输入流中移走
  • Read,将字符读入到字符数组中
  • ReadBlock,将字符持续读入到字符数组或者块中,直到读入了足够的字符数或者到达了文件尾
  • ReadLine,读入一行字符,并将其作为字符串返回
  • ReadToEnd,一直读入到流的尾部,并将所有的字符作为一个字符串返回
  • Synchronized,创建一个TextReader的一个线程安全包

5.StreamReader

StreamReader类支持流中的面向字符的输入,因此该类可以用来从文件中逐行读取文本。StreamReader可以使用任何一种选定的字符编码方式,但在默认情况下使用的是UTF-8方式,因为这种编码方式可以处理统一编码标准下的字符。
在创建StreamReader时,根据下面的不同情况的参数,共有10中可选的构造器以不同的方式来创建对象:

  • ① 根据文件名,也可以不指定字符编码方式
  • ② 根据Stream引用,同样也可以不指定编码方式

StreamReader类共有两个属性:BaseStream,用来返回对该类中所包含的Stream的引用;CurrentEncoding,用来返回当前reader对象所使用的的字符编码方式。
StreamReader中包含有好几种不同的读取数据的方式。ReadLine()方法用来读取某一行数据,并将其作为字符串返回。ReadToEnd()方法用来读取整个流,也是以一个字符串的形式返回。同时还有两种Read()方法,其中一种用来返回流中的下一个字符(如果已经到达了流的末尾,则返回-1),另一种用来将指定数量的字符读入到下一个字符数组中。此外,可以通过Peek()方法浏览流中的下一个字符而不将其中流中移走。

6.StringReader

使用StringReader可以从字符串中读取字符,每次可以读取一个、多个或者是一整行字符。如果需要把字符串当作文本文件来处理,这个类是很有用的。

7.应用举例

读入每一个C#文件,将每行中的注释去掉,并加上行号,写入另一文件:

using System;
using System.IO;
using System.Text;

namespace ConsoleApp18流_文件IO
{
    
    
	class CopyFileAddLineNumber
	{
    
    
		public static void MMain(string[] args) {
    
    
			string infname = @"E:\Visual Studio 2019\C#\Mooc学习\ConsoleApp18流、文件IO\CopyFileAddLineNumber.cs";
			string outfname = "CopyFileAddLineNumber.txt";
			if (args.Length >= 1) infname = args[0];
			if (args.Length >= 2) outfname = args[1];
			try {
    
    
				FileStream fin = new FileStream(infname, FileMode.Open, FileAccess.Read);
				FileStream fout = new FileStream(outfname, FileMode.Create, FileAccess.Write);

				StreamReader brin = new StreamReader(fin, Encoding.Default);
				StreamWriter brout = new StreamWriter(fout, Encoding.Default);

				int cnt = 0;    // 行号
				string s = brin.ReadLine();
				while (s != null) {
    
    
					cnt++;
					s = deleteComments(s);                  // 去掉以 // 开始的注释
					brout.WriteLine(cnt + ":\t" + s);       // 写入
					Console.WriteLine(cnt + ":\t" + s);     // 在控制上显示
					s = brin.ReadLine();                    // 读入
				}

				brin.Close();               // 关闭缓冲读入流及文件读入流的连接
				brout.Close();
			} catch (FileNotFoundException) {
    
    

				Console.WriteLine("File not found!");
			} catch (Exception e2) {
    
    

				Console.WriteLine(e2);
			}

		}

		private static string deleteComments(string s) {
    
        // 去掉以 // 开始的注释

			if (s == null) return s;
			int pos = s.IndexOf("//");
			if (pos < 0) return s;
			return s.Substring(0, pos);
		}
	}
}

运行结果:
在这里插入图片描述

使用File的文本文件功能

文本文件的处理是比较常用的,所以.NET Framework提供了专门的File类来处理文本文件的相关功能,File是个static类,直接使用“File.方法”即可。
这些方法中,一类是得到一个流以方便操作,如File.OpenText(path)File.AppendText(path)得到一个UTF-8编码的StreamWriter,而File.OpenText(path)得到一个UTF-8编码的StreamReader
另一类则更方便,打开、读写、关闭文件只有一个方法就行了,包括:

  • File.ReadAllText(path, encoding)读到一个文件的所有文本
  • File.ReadAllLines(path, encoding)读到一个文件的所有行的数组
  • File.WriteAllText(path, text, encoding)将文本写入到一个文件中
  • File.WriteAllLines(path, lines, encoding)将文本数组写入到一个文件中
  • File.AppendAllText(path, text, encoding)将文本附加到一个文件中
  • FIle.AppendAllLines(path, lines, encoding)将文本数组附加到一个文件中

另外,还有一个File.ReadAllBytes(path)可以一次性地读入任意文件所有字节内容。
例,FileReadWrieText()使用File类来读写文件:

	public static void FileReadwriteText() {
    
    
		string path = @"E:\Visual Studio 2019\C#\Mooc学习\ConsoleApp18流、文件IO\bin\Debug\FileText.txt";
	
		// 创建文件(UTF-8编码)
		if (!File.Exists(path)) {
    
    
			using (StreamWriter sw = File.CreateText(path)) {
    
    
				sw.WriteLine("Hello");
				sw.WriteLine("And");
				sw.WriteLine("Welcome");
			}
		}
	
		// 读文件(UTF-8编码)
		using (StreamReader sr = File.OpenText(path)) {
    
    
			string s = "";
			while ((s = sr.ReadLine()) != null) {
    
    
				Console.WriteLine(s);
			}
		}
	}

例,FileReadWriteAlLines使用File类来一次性读写文本文件。

	public static void FileReadwriteAllLines() {
    
    
		string path = @"E:\Visual Studio 2019\C#\Mooc学习\ConsoleApp18流、文件IO\bin\Debug\FileText1.txt";
		Encoding encoding = Encoding.Default;

		// 一次性写入文件内容
		File.WriteAllText(path, "hello\nworld\n", encoding);

		// 一次性追加文件内容
		File.AppendAllLines(path, new string[] {
    
     "good", "file" }, encoding);

		// 一次性读文件内容
		string[] lines = File.ReadAllLines(path, encoding);
		foreach (string s in lines)
			Console.WriteLine(s);
	}

标准输入/输出

计算机系统都有默认的标椎输入设备和输出设备。对一般的系统,标准输入通常是键盘,标准输出通常是显示器屏幕。C#程序使用字符界面与系统标准输入/输出间进行数据通信,即从键盘读入数据,或向屏幕输出数据,是十分常见的操作。
在C#中可以用Console来处理控制台的操作。Console有三个static的属性:Console.InConsole.OutConsole.Error,分别于系统的标准输入、标准输出及标准错误输出相联系。
Console.InTextReader类的对象,Console.OutConsole.ErrorTextWriter类的对象。可以用它们来进行各种各样的读写操作。
事实上,Console.Read()Console.ReadLine()Console.Write()Console.WriteLine()这几个方法会将相应的操作转向到Console.InConsole.Out

猜你喜欢

转载自blog.csdn.net/qq_45349225/article/details/114419443