2010-05-24 17 views
0

我想製作一個簡單的文本文件查看器,並且希望它能夠處理大型文件(可能大於計算機內存)。帶滑動緩衝區的文件查看器

我知道我需要實現類似滑動緩衝區的東西,它將包含文件的當前可見部分。主要問題是確定線條和文件偏移之間的關係。如果我只是需要能夠按行瀏覽,我只需要一個的鏈接列表,並在行上/行下從文件中讀取新行。但是當我也想去時,我應該怎麼做,比如說50%的文件?我需要顯示從文件一半開始的行,所以如果文件長度爲10000字節,我會尋找字節5000,查找換行符並從那裏顯示內容。問題是,我不知道我在尋求這樣的線路時會遇到什麼問題。

所以我想知道的是將這幾行內容保留在屏幕上的合適數據結構是什麼。

請記住,我不需要編輯文件,只需查看它們,所以我不需要關心所選方法的編輯效率。

回答

0

如果您正在通過FileStream定義的字節塊中讀取,則可以跟蹤上次讀取哪個字節,以便知道在哪裏接下來從文件中讀取更多數據塊。 FileStream公開了Read(),它允許您指定一個偏移字節(開始的位置)以及一次要讀取的字節數。

讀完字節後,您可以使用解碼器將它們解碼爲UTF8,然後使用解碼器檢索字符數組。所有這些都應該初始化你的初始數據。我會做什麼,因爲這將顯示在某個地方是設置事件處理程序綁定到滾動。當您開始向下滾動時,您可以刪除內存中的頂部行(同時在刪除之前計算它們的字節數,以便您可以動態讀取下一組具有相同大小的字節)並將新行添加到底部。同樣向上滾動。

如果你想弄清楚你的一半數據,那麼你可以嘗試在文本文件路徑上使用FileInfo對象,然後使用Length()方法返回字節數。由於流以字節爲單位進行處理,因此嘗試讀取百分比時非常方便。您可以使用它來定義要讀入的字節數。您必須讀取數據才能確定換行符的位置,並將讀取的最後一個字節設置爲CR-LF,以便在再次檢索數據時從下一行讀取。

下面是我會做什麼從文件中讀取預定義的字節數。

public static LastByteRead = 0; // keep it zero indexed 

public String[] GetFileChunk(String path, long chunkByteSize) 
{ 
    FileStream fStream; 
    String[] FileTextLines; 
    int SuccessBytes = 0; 
    long StreamSize; 
    byte[] FileBytes; 
    char[] FileTextChars; 
    Decoder UtfDecoder = Encoding.UTF8.GetDecoder(); 
    FileInfo TextFileInfo = new FileInfo(path); 

    if(File.Exists(path)) 
    { 
     try { 
      StreamSize = (TextFileInfo.Length >= chunkByteSize) ? chunkByteSize : TextFileInfo.Length; 
      fStream = new FileStream(path, FileMode.Open, FileAccess.Read); 
      FileBytes = new byte[ StreamSize ]; 
      FileTextChars = new char[ StreamSize ]; // this can be same size since it's UTF-8 (8bit chars) 

      SuccessBytes = fStream.Read(FileBytes, 0, (Int32)StreamSize); 

      if(SuccessBytes > 0) 
      { 
       UtfDecoder.GetChars(FileBytes, 0, StreamSize, FileTextChars, 0); 
       LastByteRead = SuccessBytes - 1; 

       return 
        String.Concat(fileTextChars.ToArray<char>()).Split('\n'); 
      } 

      else 
       return new String[1] {""}; 
     } 

     catch { 
      var errorException = "ERROR: " + ex.Message; 
      Console.Writeline(errorException); 
     } 

     finally { 
      fStream.Close(); 
     } 
    } 
} 

也許這會讓你至少在正確的方向。