C#大杂烩&&Strem流与二进制输入输出详解(FileStream,StreamReader,BinaryReader)例:从命令行上接收两个文件名,挑出不同的内容,以及比较长度

C#大杂烩&&Strem流与二进制输入输出详解(FileStream,MemoryStream,BufferedStream)

首先,要操作文件,需要引入System.IO,即在代码开头using System.IO;
System.in中提供了许多用于文件和数据流进行读写操作的类,如Stream类,读写类等等,而这些类中
提供了很多针对文件、文件夹的操作功能,以及对各种数据进行访问。

那么我们分别介绍所有的类,分为三大块,1 Stream有关的类,2 与读写有关的类,3 与操作文本有关的类

一 Stream有关的类

• FileStream:

有助于文件的读写与关闭。该类派生自抽象类 Stream。
通过 FileStream 可以创建一个新的文件,或打开一个已有的文件。创建 FileStream 对象的语法如下:
而创建还是打开,是由构造函数中的第二个参数FileMode(就是一个枚举)决定的

FileStream <object_name> = new FileStream( <file_name>,
<FileMode Enumerator>, <FileAccess Enumerator>, <FileShare Enumerator>);

比如

FileStream file1 = new FileStream(name1,FileMode.Open, FileAccess.Read,FileShare.Read);

对于构造函数,FileMode和FileAccess和FileShare有以下类型

FileMode

Append :打开一个已有的文件,并将光标放置在文件的末尾。如果文件不存在,则创建文件。
Create :创建一个新的文件。如果文件已存在,则删除旧文件,然后创建新文件。
CreateNew :指定操作系统应创建一个新的文件。如果文件已存在,则抛出异常。
Open :打开一个已有的文件。如果文件不存在,则抛出异常。
OpenOrCreate :指定操作系统应打开一个已有的文件。如果文件不存在,则用指定的名称创建一个新的文件打开。
Truncate :打开一个已有的文件,文件一旦打开,就将被截断为零字节大小。然后我们可以向文件写入全新的数据,但是保留文件的初始创建日期。如果文件不存在,则抛出异常。
• MemoryStream:对一个byte数组进行流式读写
• BufferedStream:缓存操作,用于减少对文件读写次数 ,一般不单独使用,会
包装到其他类型的流中

FileAccess

Read
ReadWrite
Write。

FileShare

Inheritable:允许文件句柄可由子进程继承。Win32 不直接支持此功能。
None:谢绝共享当前文件。文件关闭前,打开该文件的任何请求(由此进程或另一进程发出的请求)都将失败。
Read:允许随后打开文件读取。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取的请求(由此进程或另一进程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
ReadWrite:允许随后打开文件读取或写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取或写入的请求(由此进程或另一进程发出)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
Write:允许随后打开文件写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行写入的请求(由此进程或另一进过程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
Delete:允许随后删除文件。

然后我们就可以使用<object_name>操作这个文件了。
FileStream常用的属性和方法:
属性:
CanRead 判断当前流是否支持读取,返回bool值,True表示可以读取
CanWrite 判断当前流是否支持写入,返回bool值,True表示可以写入
方法:
Read() 从流中读取数据,返回字节数组
Write() 将字节块(字节数组)写入该流
Seek() 设置文件读取或写入的起始位置
Flush() 清除该流缓冲区,使得所有缓冲的数据都被写入到文件中
Close() 关闭当前流并释放与之相关联的所有系统资源
例子

FileStream fsw = new FileStream("test.dat",
FileMode.Create, FileAccess.Write,FileShare.Read);
//Write some data to the stream;
fsw.WriteByte(33);
fsw.Write(new byte[] { 34, 35, 36 }, 0, 3);
fsw.Close();
FileStream fsr = new FileStream("test.dat",
FileMode.Open, FileAccess.Read);
for (int b = fsr.ReadByte(); b!=-1; b = fsr.ReadByte()){
Console.WriteLine(b);
}

• MemoryStream

对一个byte数组进行流式读写,MemoryStream是内存流,为系统内存提供读写操作,MemoryStream
的重要性不亚于FileStream,在很多场合使用它来提高性能
例子

byte[] ary = { 33, 34, 35, 36, 37 };
MemoryStream msr = new MemoryStream(ary);
MemoryStream msw = new MemoryStream();
int b;
while ((b = msr.ReadByte()) != -1){
msw.WriteByte((byte)(b + 3));
}
byte[] result = msw.ToArray();
Array.ForEach(result, bt => Console.WriteLine(bt));

• BufferedStream

缓存操作,用于减少对文件读写次数 ,一般不单独使用,会
包装到其他类型的流中

二 与读写有关的类

二进制读写

• BinaryReader和BinaryWriter

• 通过流读写基本数据类型(int、double等),而不是原始的字节类型,使用起来更方便
BinaryReader方法
在这里插入图片描述

BinaryWriter方法
在这里插入图片描述
例子

FileStream ds = new FileStream("test.dat", FileMode.Create,FileAccess.ReadWrite);
BinaryWriter bw = new BinaryWriter(ds);
//写入各种类型数据;
bw.Write("A string");
bw.Write(142);
bw.Write(97.4);
bw.Write(true);
// 打开文件进行读取数据;
BinaryReader br = new BinaryReader(ds);
// 移动到文件开头;
br.BaseStream.Seek(0, SeekOrigin.Begin);
// 读取各种类型数据;
Console.WriteLine(br.ReadString());
Console.WriteLine(br.ReadInt32());
Console.WriteLine(br.ReadDouble());
Console.WriteLine(br.ReadBoolean());

三 与操作文本有关的类(最常用的StreamReader和StreamWriter)

• 抽象类:TextReader和TextWriter
• 对文本字节流进行读写:StreamReader和StreamWriter
StreamReader的常用方法
在这里插入图片描述
StreamWriter的常用方法
在这里插入图片描述
例子

FileStream fin = new FileStream( "CopyFileAddLineNumber.cs", 
FileMode.Open, FileAccess.Read );
FileStream fout = new FileStream("CopyFileAddLineNumber.txt", 
FileMode.Create, FileAccess.Write );
StreamReader brin = new StreamReader( fin, System.Text.Encoding.Default );
StreamWriter brout = new StreamWriter(fout, System.Text.Encoding.Default );
int cnt = 0;
for (string s = brin.ReadLine(); s != null; s = brin.ReadLine()){
cnt ++; 
s = deleteComments(s);
brout.WriteLine(cnt + ": \t" + s );
Console.WriteLine(cnt + ": \t" + s );
}
brin.Close();
brout.Close();

• 对字符串进行读写:StringReader和StringWriter
• 对控制台进行读写:Console.In和Console.Out

一个比较全面的例子
从命令行上接收两个文件名,比较两个文件的长度和内容

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {

		public static string CompareTxtLength(string name1,string name2)
		{
			FileStream file1 = new FileStream(name1,FileMode.Open, FileAccess.Read);
			FileStream file2 = new FileStream(name2,FileMode.Open, FileAccess.Read);
			if (file1.Length > file2.Length)
				return name1 + "的长度大于" + name2 + "的长度。";
			else  if (file1.Length < file2.Length)
				return name1 + "的长度小于" + name2 + "的长度。";
			else
				return name1 + "的长度等于" + name2 + "的长度。";
			

				
		}
		public static void CompareTxtContact(string name1, string name2)
		{
			try
			{
				int UnsameNum = 0;
				int i = 0;
				List<long> UnSameInt = new List<long>();
				FileStream file1 = new FileStream(name1, FileMode.Open, FileAccess.Read);
				FileStream file2 = new FileStream(name2, FileMode.Open, FileAccess.Read);
				StreamReader Sf1 = new StreamReader(file1, System.Text.Encoding.Default);
				StreamReader Sf2 = new StreamReader(file2, System.Text.Encoding.Default);
				Console.WriteLine("File1:");
				while (!Sf1.EndOfStream)
				{
					char S1 = (char)Sf1.Read();
					Console.Write(S1);
				}
				file1.Position = 0;
				Console.WriteLine("File2:");
				while (!Sf1.EndOfStream && !Sf2.EndOfStream)
				{
					char S1 = (char)Sf1.Read();
					char S2 = (char)Sf2.Read();
					if (S1 == S2)
					{
						Console.Write(S2);
					}
					else
					{
						UnsameNum++;
						UnSameInt.Add(i);
						Console.Write(S2);
					}
					i++;
				}
				Sf1.Close();
				Sf2.Close();
				Console.Write("一共有" + UnsameNum + "处不同,分别在以下位置");
				foreach (long x in UnSameInt)
				{
					Console.Write(x+" ");
				}
			}
			catch(FileNotFoundException e)
			{
				Console.Write("File Not Found");
			}
		}
			
	


		static void Main(string[] args)
		{
			string name1,name2; //姓名          
			Console.Write("请输入第一个需要比较的文件地址:");     
			name1 = Console.ReadLine();//接受控制台输入的一个字符串     
			Console.Write("请输入第二个需要比较的文件地址:");
			name2 = Console.ReadLine();//接受控制台输入的一个字符串     
			Console.Write(Program.CompareTxtLength(name1, name2));
			Program.CompareTxtContact(name1, name2);
			Console.ReadLine();
		}


	}
}

原创文章 66 获赞 39 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44739495/article/details/105150284