.NET中的流

时间:2023-03-09 19:18:52
.NET中的流

当应用程序需要和磁盘上的文件打交道的时候,就有了流的概念。流就像架设在应用程序所在内存和磁盘之间的一个管道。

大致思路

→ 建立管道

//FileMode.Open打开现有文件,另外还有FileMode.Create, FileMode.Append
//FileAccess表示对文件的操作权限FileAccess.Read, FileAccess.Write, FileAccess.ReadWrite
//FileMode和FileAccess搭配使用
Stream pipe = new FileStream(@"C:\temp.png", FileMode.Open, FileAccess.Read);

→ 应用程序一般提供一个临时字节数组,用来传递数据

byte[] buffer = new byte[pipe.length];

→ 把流中的数据读到buffer数组中

//读到那里,从哪个地方开始读,读多少
//一般2GB一下的文件采用此方法
//返回读取到的字节数,当返回0表示读到了文件的结尾,流的终点
int bytesRead = pipe.Read(buffer, , (int)pipe.Length); 如果此时想把字节数组buffer显示出来,按如下: foreach(var item in buffer)
{
//显示成二进制
Console.Write(item.ToString(item, ));
}

→ 再把buffer中的字节保存到磁盘文件

Stream target = new FileStream(@"C:\target.png", FileMode.Create, FileAccess.Write);
target.Write(buffer, , buffer.Length);
target.Dispose();

分批复制

如果文件比较大,那就需要分批复制了。我们可以根据int bytesRead = pipe.Read(buffer, 0, (int)pipe.Length);中,bytesRead如果大于0就让循环,等于0说明已经读到源头流的结尾了。

//先定义临时字节数组的大小
int BufferSize = ; //源头流
Stream from = new FileStram(@"C:\bigger.png", FileModel.Open, FileAcess.Read); //目标流
Stream to = new FielStream(@"C:\biggertarget.png", FileMode.Create, FileAccess.Write); byte[] buffer = new byte[BufferSize];
int bytesRead;
do {
bytesRead = from.Read(buffer, , BufferSize);
to.Write(buffer, , BufferSize);
} while (bytesRead > ) from.Dispose();
to.Dispose();

流的家族成员

以上,了解了流的读取和写入,现在来了解下流的家族成员。

Stream是一个基类,抽象类,基本家族成员包括:

Stream
    FileStream
    MemoryStream
    NetworkStream
    
现实情况是有更多的流,比如加密流、压缩流等,这些流不仅有Stream的所有特征,还有自己的个性。这时候,用"装饰器模式"再好不过了。在这里,"装饰器模式"体现在:不仅继承Stream类,还引用Stream类。这些通过"装饰器模式"来实现的流包括:BufferedStream, DeflateStream, GZipStream, CryptoStream, AuthenticateStream.

流的操作有很多,.NET为我们封装了StreamReader和StreamWriter来对流进行操作,我们需要把流作为引用传入。基本用法如下:

FileStream from = new FileStream("C:\temp.txt", FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(from, Encoding.GetEncoding("GB2312"));
...
reader.Dispose();

以上,适合于读取或写入文本。

当涉及到二进制的读取和写入时,.NET为我们封装了BinaryReader和BinaryWriter。基本用法如下:

public class Book
{
public int Id{get;set;}
public string Name{get;set;}
public decimal Price{get;set;} private string saveFilePath = string.Empty; public Book(string saveFilePath)
{
this.saveFilePath = saveFilePath;
} public void SaveBook()
{
FileStream fs = new FileStream(this.saveFilePath, FileMode.Create, FileAccess.Write);
BinaryWriter writer = new BinaryWriter(fs);
writer.Write(this.Id);
writer.Write(this.Name);
writer.Write(this.Price);
writer.Dispose();
} publci void LoadBook()
{
FileStream fs = new FileStream(this.saveFilePath, FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(fs);
this.Id = reader.ReadInt32();
this.Name = reader.ReadString();
this.Price = reader.ReadDouble();
reader.Dispose();
} public override string ToString()
{
return string.Format("Id:{0}, Name: {1}, Price: {2}", this.Id, this.Name, this.Price);
}
} var book = new Book("C:\book.txt"){
Id = ,
Name = "",
Price =
};
book.SaveBook();

另外,不仅可以通过诸如new FileStream的构造函数创建流,.NET还为我们提供了产生流的静态帮助类和静态方法,比如File和FileInfo等,用法大致是:
FileStream fs = File.Create("C:\temp.jpg");