當應用程式需要和磁碟上的文件打交道的時候,就有了流的概念。流就像架設在應用程式所在記憶體和磁碟之間的一個管道。 大致思路 → 建立管道 //FileMode.Open打開現有文件,另外還有FileMode.Create, FileMode.Append //FileAccess表示對文件的操作許可權Fi
當應用程式需要和磁碟上的文件打交道的時候,就有了流的概念。流就像架設在應用程式所在記憶體和磁碟之間的一個管道。
大致思路
→ 建立管道
//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, 0, (int)pipe.Length); 如果此時想把位元組數組buffer顯示出來,按如下: foreach(var item in buffer) { //顯示成二進位 Console.Write(item.ToString(item, 2)); }
→ 再把buffer中的位元組保存到磁碟文件
Stream target = new FileStream(@"C:\target.png", FileMode.Create, FileAccess.Write); target.Write(buffer, 0, buffer.Length); target.Dispose();
分批覆制
如果文件比較大,那就需要分批覆制了。我們可以根據int bytesRead = pipe.Read(buffer, 0, (int)pipe.Length);中,bytesRead如果大於0就讓迴圈,等於0說明已經讀到源頭流的結尾了。
//先定義臨時位元組數組的大小 int BufferSize = 1024; //源頭流 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, 0, BufferSize); to.Write(buffer, 0, BufferSize); } while (bytesRead > 0) 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 = 1, Name = "", Price = 8 }; book.SaveBook();
另外,不僅可以通過諸如new FileStream的構造函數創建流,.NET還為我們提供了產生流的靜態幫助類和靜態方法,比如File和FileInfo等,用法大致是:
FileStream fs = File.Create("C:\temp.jpg");