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();
}
}
}