如何有效的使用C#读取文件
你平時是怎么讀取文件的?使用流讀取。是的沒錯,C#給我們提供了非常強大的類庫(又一次吹捧了.NET一番),里面封裝了幾乎所有我們可以想到的和我們沒有想到的類,流是讀取文件的一般手段,那么你真的會用它讀取文件中的數據了么?真的能讀完全么?
通常我們讀取一個文件使用如下的步驟:
1、聲明并使用File的OpenRead實例化一個文件流對象,就像下面這樣
???????FileStream?fs?=?File.OpenRead(filename);
或者
???????FileStream?fs?=?FileStream(filename,?FileMode.Open,?FileAccess.Read,?FileShare.Read);
2、準備一個存放文件內容的字節數組,fs.Length將得到文件的實際大小,就像下面這樣
???????byte[]?data?=?new?byte[fs.Length];
3、哇!開始讀了,調用一個文件流的一個方法讀取數據到data數組中
???????fs.Read?(data,?0,?data.Length);
呵呵!我們只寫了3句就可以把文件里面的內容原封不動的讀出來,真是太簡潔了!可以這段代碼真的能像你預期的那樣工作么?答案是:幾乎可以!在大部分情況下上面的代碼工作的很好,但是我們應該注意Read方法是有返回值的,既然有返回值那么一定有其道理,如果按照上面的寫法完全可以是一個沒有返回值的函數。我想返回值的目的是,為了給我們一個機會判斷實際讀取文件的大小,從而來判斷文件是否已經完全讀完。所以上面的代碼不能保證我們一定讀完了文件里面的所有字節(雖然在很多情況下是讀完了)。下面的方法提供了一個比上面方法更安全的方法,來保證文件被完全讀出
public?static?void?SafeRead?(Stream?stream,?byte[]?data){
????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;
????}
}
?
有些情況下你不知道流實際的長度比如:網絡流。此時可以使用類似的方法讀取流直到流里面的數據完全讀取出來為止。我們可以先初始化一段緩存,再將流讀出來的流信息寫到內存流里面,就像下面這樣:
public?static?byte[]?ReadFully?(Stream?stream){
???????//?初始化一個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);
????????}
????}
}
?
雖然上面的例子都比較簡單,效果也不是很明顯(大部分都是對的),也許你早就會了,沒關系這篇文章本來就是寫給初學者的。
下面的方法提供了一種使用指定緩存長度的方式讀取流,雖然在很多情況下你可以直接使用Stream.Length得到流的長度,但是不是所有的流都可以得到。
public?static?byte[]?Read2Buffer?(Stream?stream,?int?BufferLen){
???????//?如果指定的無效長度的緩沖區,則指定一個默認的長度作為緩存大小
???????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,然后直接返回
???????byte[]?ret?=?new?byte[read];
???????Array.Copy(buffer,?ret,?read);
???????return?ret;
}
using?System;using?System.IO;
using?System.Collections;
namespace?TextFileReader_csharp
{
///?<summary>
///?Summary?description?for?Class1.
///?</summary>
class?Class1
{
static?void?Main(string[]?args)
{
StreamReader?objReader?=?new?StreamReader("c://test.txt");
string?sLine="";
ArrayList?arrText?=?new?ArrayList();
while?(sLine?!=?null)
{
sLine?=?objReader.ReadLine();
if?(sLine?!=?null)
arrText.Add(sLine);
}
????????????????????????objReader.Close();
foreach?(string?sOutput?in?arrText)
Console.WriteLine(sOutput);
Console.ReadLine();
}
}
}?
總結
以上是生活随笔為你收集整理的如何有效的使用C#读取文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 发送邮件程序(Csharp2005)
- 下一篇: C#中Base64之编码,解码方法