2009-05-06 49 views
1

我試圖解析一個文本文件,該文件具有標題和正文。在這個文件的標題中,有正文部分的行號參考。例如:在C#中跳過一些內容解析文本文件

SECTION_A 256 
SECTION_B 344 
SECTION_C 556 

這意味着,SECTION_A始於線256

什麼是解析這個標題到字典中,然後在需要時閱讀部分的最佳方式。

典型場景將是:

  1. 解析報頭和只讀部分SECTION_B
  2. 解析報頭和讀取的每個段的段的拳頭。

數據文件非常大,我絕對不想將它全部加載到內存中,然後對其進行操作。

我很感激你的建議。我的環境是VS 2008和C#3.5 SP1。

回答

2

好吧,顯然你可以將名字+行號存儲到字典中,但這對你沒有任何好處。

嗯,當然,它會讓你知道哪一行開始讀取,但問題是,文件中的哪一行是?知道的唯一方法是從頭開始並開始計數。

最好的辦法是編寫一個解碼文本內容的包裝器(如果你有編碼問題),並且可以給你一個行號到字節位置類型的映射,那麼你可以取這個行號,256和在字典中查找以知道該行256從文件中的位置10000開始,並從那裏開始讀取。

這是一次性加工情況嗎?如果沒有,你有沒有考慮把整個文件填充到本地數據庫中,比如SQLite數據庫?這將允許您在行號和其內容之間有直接映射。當然,該文件會比原始文件更大,並且您需要將文本文件中的數據複製到數據庫,因此無論哪種方式都有一些開銷。

+0

謝謝,我擔心在開始操作之前,我將不得不預先處理文件。外部數據庫對我來說不是一種選擇,因爲數據文件變化太頻繁,無論如何,謝謝你的回答 – 2009-05-06 19:25:57

+0

你可能懶惰,只做從開始到你感興趣的部分的預處理。每次訪問從0到那個點將是.Seek():能夠,如果你對後面的部分感興趣,你可以繼續從你離開的地方進行預處理。同時存儲帶有時間戳和任何可識別信息的索引供以後使用(或在數據更新時徹底刪除它)。 – 2009-05-06 19:40:27

+0

我喜歡Pasi的建議,謝謝! – 2009-05-06 19:47:53

0

只要一次讀取一行文件,並忽略數據,直到找到所需的數據。你不會有任何內存問題,但性能可能不會很好。你可以在後臺線程中輕鬆完成。

0

讀取文件直到標題結束,假設您知道它在哪裏。拆你存儲在空白的字符串,像這樣:

Dictionary<string, int> sectionIndex = new Dictionary<string, int>(); 
List<string> headers = new List<string>(); // fill these with readline 

foreach(string header in headers) { 
    var s = header.Split(new[]{' '}); 
    sectionIndex.Add(s[0], Int32.Parse(s[1])); 
} 

找到你想要的字典項,保留的行數的計數文件中讀取,以及循環播放,直到你打的行號,然後直到你到達下一節的起跑線。我不知道你是否可以保證字典中鍵的順序,所以你可能需要當前和下一節的名字。

請務必做一些錯誤檢查,以確保您正在閱讀的部分不在您正在閱讀的部分之前,以及您可以想到的任何其他錯誤情況。

0

您可以逐行閱讀,直到捕獲所有標題信息並停止(假設所有節指針都在標題中)。您將有用於稍後檢索數據的部分和行號。

string dataRow = ""; 

try 
{ 
    TextReader tr = new StreamReader("filename.txt"); 

    while (true) 
    { 
     dataRow = tr.ReadLine(); 
     if (dataRow.Substring(1, 8) != "SECTION_") 
      break; 
     else 
      //Parse line for section code and line number and log values 
      continue; 
    } 
    tr.Close(); 
} 
catch (Exception ex) 
{ 
    MessageBox.Show(ex.Message); 
} 
3

你可以很容易地做到這一點。

這個問題有三個部分。

1)如何找到文件中的一行開始。做到這一點的唯一方法是從文件中讀取行,保留一個列表,記錄該行文件中的起始位置。例如

 
List lineMap = new List(); 
lineMap.Add(0); // Line 0 starts at location 0 in the data file (just a dummy entry) 
lineMap.Add(0); // Line 1 starts at location 0 in the data file 

using (StreamReader sr = new StreamReader("DataFile.txt")) 
{ 
    String line; 
    int lineNumber = 1; 
    while ((line = sr.ReadLine()) != null) 
     lineMap.Add(sr.BaseStream.Position); 
} 

2)讀取並解析索引文件到字典中。

 
Dictionary index = new Dictionary(); 

using (StreamReader sr = new StreamReader("IndexFile.txt")) 
{ 
    String line; 
    while ((line = sr.ReadLine()) != null) 
    { 
     string[] parts = line.Split(' '); // Break the line into the name & line number 
     index.Add(parts[0], Convert.ToInt32(parts[1])); 
    } 
} 

然後找到你的文件中的一行,使用方法:

 
int lineNumber = index["SECTION_B";];   // Convert section name into the line number 
long offsetInDataFile = lineMap[lineNumber]; // Convert line number into file offset 

然後打開DataFile.txt一個新的FileStream,尋求(offsetInDataFile,SeekOrigin.Begin)移動到的開始行,並使用StreamReader(如上所述)從中讀取行。