c#里面封裝了幾乎所有我們可以想到的和我們沒有想到的類,流是讀取文件的一般手段,那么你真的會用它讀取文件中的數據了么?真的能讀完全么?
通常我們讀取一個文件使用如下的步驟:
1、聲明并使用File的OpenRead實例化一個文件流對象,就像下面這樣
3、哇!開始讀了,調用一個文件流的一個方法讀取數據到data數組中 fs.Read (data, 0, data.Length);
呵呵!我們只寫了3句就可以把文件里面的內容原封不動的讀出來,真是太簡潔了!可以這段代碼真的能像你預期的那樣工作么?
答案是:幾乎可以!在大部分情況下上面的代碼工作的很好,但是我們應該注意Read方法是有返回值的,既然有返回值那么一定有其道理,如果按照上面的寫法完全可以是一個沒有返回值的函數。我想返回值的目的是,為了給我們一個機會判斷實際讀取文件的大小,從而來判斷文件是否已經完全讀完。所以上面的代碼不能保證我們一定讀完了文件里面的所有字節(雖然在很多情況下是讀完了)。下面的方法提供了一個比上面方法更安全的方法,來保證文件被完全讀出
{
int offset=0; int remaining = data.Length; // 只要有剩余的字節就不停的讀
while (remaining > 0)
{
int read = stream.Read(data, offset, remaining);
if (read <= 0) throw new EndOfStreamException("文件讀取到"+read.ToString()+"失??!"); // 減少剩余的字節數 remaining -= read; // 增加偏移量 offset += read;
}
}
{
// 初始化一個32k的緩存
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream()){
//返回結果后會自動回收調用該對象的Dispose方法釋放內存
// 不停的讀取 while (true){
int read = stream.Read (buffer, 0, buffer.Length); // 直到讀取完最后的
3M數據就可以返回結果了
if (read <= 0) return ms.ToArray();
ms.Write (buffer, 0, read); }
}}
{
// 如果指定的無效長度的緩沖區,則指定一個默認的長度作為緩存大小
if (BufferLen < 1){ BufferLen = 0x8000; }
// 初始化一個緩存區 byte[] buffer = new byte[BufferLen]; int read=0; int block;
// 每次從流中讀取緩存大小的數據,知道讀取完所有的流為止
while ( (block = stream.Read(buffer, read, buffer.Length-read)) > 0)
{
// 重新設定讀取位置 read += block;
// 檢查是否到達了緩存的邊界,檢查是否還有可以讀取的信息
if (read == buffer.Length){
// 嘗試讀取一個字節 int nextByte = stream.ReadByte();
// 讀取失敗則說明讀取完成可以返回結果 if (nextByte==-1){ return buffer; }
// 調整數組大小準備繼續讀取
byte[] newBuf = new byte[buffer.Length*2]; Array.Copy(buffer, newBuf, buffer.Length);
newBuf[read]=(byte)nextByte; buffer = newBuf;
// buffer是一個引用(指針),這里意在重新設定buffer指針指向一個更大的內存 read++; }
} // 如果緩存太大則使用ret來收縮前面while讀取的buffer,
Array.Copy(buffer, ret, read); return ret;}
新聞熱點
疑難解答