2014-01-05 65 views
0

我正在使用一個項目,而且我有點困惑。我從我的老師那裏得到了一些txt文件(來自his site文件:wt40.txt,wt50.txt,wt100.txt)。用C#讀取txt文件的最快方法

每個文件結構看起來similiar:

26 24 79 46 32 35 73 74 14 67 86 46 78 40 29 94 64 27 90 55 
35 52 36 69 85 95 14 78 37 86 44 28 39 12 30 68 70  9 49 50 
1 10  9 10 10  4  3  2 10  3  7  3  1  3 10  4  7  7  4  7 
5  3  5  4  9  5  2  8 10  4  7  4  9  5  7  7  5 10  1  3 
  • 每個數字在6個字符,但而不是前導零有 空間
  • 在每行有20個號碼

文件wt40.txt應該被讀爲:前兩行到第一列表,下兩行到下一列表和第三對行到第三列表。下一行再次應該與這些列表配對。

在C++中,我做這個簡單的方法:

for(int ins=0; ins<125; ins++) //125 instances in file 
{ 
    for(int i=0; i<N; i++) file>>tasks[i].p; //N elements at two first lines 
    for(int i=0; i<N; i++) file>>tasks[i].w; 
    for(int i=0; i<N; i++) file>>tasks[i].d; 
    tasks[i].putToLists(); 
} 

但是,當我在寫這在C#我要打開的StreamReader,讀每一行,用正則表達式分割它,將它們轉換成int並添加到列表中。這是很多循環。 我無法讀取每6個字符,並將它們添加到三個循環中,因爲這些文本文件已經混淆了字符行結束 - 有時它只是'\ n'有時更多。

難道還沒有更簡單的方法嗎?

+3

調查File.ReadAlLines和String.Split。此外,在C#問題中,我們期望C#代碼(嘗試解決方案),而不是C++。 –

+1

此外,作爲問題的一部分,張貼您的數據文件的摘錄。 –

+2

與問題的語義有關的一個小細節 - 閱讀總是「相同」(tm)速度 - 它超出了你的控制範圍。但是,它會逐行處理數據,減慢讀取速度。 – Gusdor

回答

1

基本上有一個由6個數字(字符)數字組成的具有前導空格的20乘n表。

26 24 79 46 32 35 73 74 14 67 86 46 78 40 29 94 64 27 90 55 
35 52 36 69 85 95 14 78 37 86 44 28 39 12 30 68 70  9 49 50 
1 10  9 10 10  4  3  2 10  3  7  3  1  3 10  4  7  7  4  7 
5  3  5  4  9  5  2  8 10  4  7  4  9  5  7  7  5 10  1  3 

我不明白,最後一句:wt40.txt應該讀作

文件:第一行到第一個List,未來 兩行下一個列表和第三對線到第三個名單。接下來 行應再次成對的列表。

說你要獲得前6行創建的每個3只列出了2行,你做的可能是這樣的:

正是在它讀取的一切到內存渴望,然後做其工作。

const int maxNumberDigitLength = 6; 
const int rowLengthInChars = maxNumberDigitLength * 20; 
const int totalNumberOfCharsToRead = rowLengthInChars * maxNumberDigitLength; 

char[] buffer = new char[totalNumberOfCharsToRead]; 
using (StreamReader reader = new StreamReader("wt40.txt") 
{ 
    int numberOfCharsRead = reader.Read(buffer, 0, totalNumberOfCharsToRead); 
} 

// put them in your lists 
IEnumerable<char> l1 = buffer.Take(rowLengthInChars); 
IEnumerable<char> l2 = buffer.Skip(rowLengthInChars).Take(rowLengthInChars); 
IEnumerable<char> l3 = buffer.Skip(rowLengthInChars*2).Take(rowLengthInChars); 

// Get the list of strings from the list of chars using non LINQ method. 
List<string> list1 = new List<string>(); 
int i = 0; 
StringBuilder sb = new StringBuilder(); 
foreach(char c in l1) 
{ 
    if(i < maxNumberDigitLength) 
    { 
     sb.Append(c); 
     i++; 
    } 
    i = 0; 
    list1.Add(sb.ToString()); 
} 

// LINQ method 
string s = string.Concat(l1); 
List<string> list1 = Enumerable 
        .Range(0, s.Length/maxNumberDigitLength) 
        .Select(i => s.Substring(i * maxNumberDigitLength, maxNumberDigitLength)) 
        .ToList();  

// Parse to ints using LINQ projection 
List<int> numbers1 = list1.Select(int.Parse); 
List<int> numbers2 = list2.Select(int.Parse); 
List<int> numbers3 = list3.Select(int.Parse); 
+1

爲什麼你要在緩衝區中調用'ToList()'? –

+0

所以我可以使用LINQ –

+0

爲什麼你經常這樣稱呼它? :) – Matten

1

是不是有什麼比較簡單的方法?

不知道它的簡單,但只有一個環和一點點LINQ

List<List<int>> lists = new List<List<int>>(); 
using (StreamReader reader = new StreamReader("wt40.txt")) 
{ 
    string line; 
    int count = 0; 
    while ((line = reader.ReadLine()) != null) 
    { 
     List<int> currentList = 
      Regex.Split(line, "\\s") 
      .Where(s => !string.IsNullOrWhiteSpace(s)) 
      .Select(int.Parse).ToList(); 
     if (currentList.Count > 0) // skip empty lines 
     { 
      if (count % 2 == 0) // append each second list to the previous one 
      { 
       lists.Add(currentList); 
      } 
      else 
      { 
       lists[count/2].AddRange(currentList); 
      } 
     } 
     count++; 
    } 
} 

在你結束了375名名單每片含40號(至少wt40.txt輸入總)。