2016-07-13 60 views
0

我想每次讀取和處理10行以上的GB文件,但還沒有找到解決方案來吐出10行直到結束。一次讀取一個文件的行數C#

我最後的嘗試是:

 int n = 10; 
     foreach (var line in File.ReadLines("path") 
      .AsParallel().WithDegreeOfParallelism(n)) 
     { 
      System.Console.WriteLine(line); 
      Thread.Sleep(1000); 
     } 

我已經看到了使用緩衝區的大小的解決方案,但我想整個行來讀。

+0

你的最後10行後是? – BugFinder

+0

你可不可以使用'.Take'函數來做到這一點,也許你可以看看這個並讓它爲你工作..一次10條線將永遠帶你..爲什麼不設置線爲300例如 看看這個鏈接 - http://stackoverflow.com/questions/11326564/reading-specific-number-of-lines-from-text-file-in-c-sharp – MethodMan

+0

你可以請澄清你的期望是什麼結果? –

回答

-1

保重ReadLines將讀取您的GB文件的所有行,不僅是您打印的 打印的行。 你真的需要並行嗎?

+0

請澄清你正在回答的問題(並確保不要輸入評論回答) –

+1

我認爲你的意思是這是一個評論而不是回答 – MikeT

+0

是的,對不起。我的錯。 –

1

默認behavour是讀取所有行在一個鏡頭,如果你想讀取少於,你需要深入瞭解它如何讀取它們,並得到一個StreamReader然後讓你控制讀取過程

 using (StreamReader sr = new StreamReader(path)) 
     { 
      while (sr.Peek() >= 0) 
      { 
       Console.WriteLine(sr.ReadLine()); 
      } 
     } 

它也有一個ReadLineAsync方法將返回一個任務

如果包含在ConcurrentBag這些任務,你可以很容易保持加工上10日線同時運行。

var bag =new ConCurrentBag<Task>(); 
using (StreamReader sr = new StreamReader(path)) 
{ 
    while(sr.Peek() >=0) 
    { 
     if(bag.Count < 10) 
     { 
      Task processing = sr.ReadLineAsync().ContinueWith((read) => { 
       string s = read.Result;//EDIT Removed await to reflect Scots comment 
       //process line 
      }); 
      bag.Add(processing); 
     } 
     else 
     { 
      Task.WaitAny(bag.ToArray()) 
      //remove competed tasks from bag 
     } 
    } 
} 

注意此代碼僅供參考,不得作爲原樣使用;

如果你想要的是最後十行,那麼你可以得到與這裏 How to read a text file reversely with iterator in C#

+1

不需要「等待讀取」,讀取被保存在完成狀態(也不會編譯,因爲匿名方法沒有標記爲異步)。只要做一個'read.Result' –

+0

當有10個任務處理時,這會在'sr.Peek()'上旋轉嗎?你如何從包裏取出完成的任務? –

+0

我總是在線程謹慎的方面犯錯,等待一些很少受到傷害的東西,但假設某些東西已經完成時,它不會造成噩夢,還請注意,我提到需要在文本中添加異步。我向他們展示瞭如何執行不爲他們做的任務 – MikeT

0

解決此方法將創建一個從您的文件中的行「頁面」。

public static IEnumerable<string[]> ReadFileAsLinesSets(string fileName, int setLen = 10) 
{ 
    using (var reader = new StreamReader(fileName)) 
     while (!reader.EndOfStream) 
     { 
      var set = new List<string>(); 
      for (var i = 0; i < setLen && reader.EndOfStream; i++) 
      { 
       set.Add(reader.ReadLine()); 
      } 
      yield return set.ToArray(); 
     } 
} 

...更多好玩的版本...

class Example 
{ 
    static void Main(string[] args) 
    { 
     "YourFile.txt".ReadAsLines() 
         .AsPaged(10) 
         .Select(a=>a.ToArray()) //required or else you will get random data since "WrappedEnumerator" is not thread safe 
         .AsParallel() 
         .WithDegreeOfParallelism(10) 
         .ForAll(a => 
     { 
      //Do your work here. 
      Console.WriteLine(a.Aggregate(new StringBuilder(), 
              (sb, v) => sb.AppendFormat("{0:000000} ", v), 
              sb => sb.ToString())); 
     }); 
    } 
} 

public static class ToolsEx 
{ 

    public static IEnumerable<IEnumerable<T>> AsPaged<T>(this IEnumerable<T> items, 
                   int pageLength = 10) 
    { 
     using (var enumerator = new WrappedEnumerator<T>(items.GetEnumerator())) 
      while (!enumerator.IsDone) 
       yield return enumerator.GetNextPage(pageLength); 
    } 

    public static IEnumerable<T> GetNextPage<T>(this IEnumerator<T> enumerator, 
                int pageLength = 10) 
    { 
     for (var i = 0; i < pageLength && enumerator.MoveNext(); i++) 
      yield return enumerator.Current; 
    } 

    public static IEnumerable<string> ReadAsLines(this string fileName) 
    { 
     using (var reader = new StreamReader(fileName)) 
      while (!reader.EndOfStream) 
       yield return reader.ReadLine(); 
    } 
} 

internal class WrappedEnumerator<T> : IEnumerator<T> 
{ 
    public WrappedEnumerator(IEnumerator<T> enumerator) 
    { 
     this.InnerEnumerator = enumerator; 
     this.IsDone = false; 
    } 

    public IEnumerator<T> InnerEnumerator { get; private set; } 
    public bool IsDone { get; private set; } 

    public T Current { get { return this.InnerEnumerator.Current; } } 
    object System.Collections.IEnumerator.Current { get { return this.Current; } } 

    public void Dispose() 
    { 
     this.InnerEnumerator.Dispose(); 
     this.IsDone = true; 
    } 

    public bool MoveNext() 
    { 
     var next = this.InnerEnumerator.MoveNext(); 
     this.IsDone = !next; 
     return next; 
    } 

    public void Reset() 
    { 
     this.IsDone = false; 
     this.InnerEnumerator.Reset(); 
    } 
} 
+0

不完全相信,如果它有多個Gb會非常快地達到這個限制,.Net有最大2Gb的內存頁面大小讀取整個文件。 – MikeT

+0

它只會讀取你記憶中的內容。如果你使用'.AsParallel()。WithDegreeOfParallelism(n))',它應該只有在任何給定時間加載的頁面數量爲n。 –

+0

是的,可以讓它變得更加懶惰,所以即使是IEnumerable中的內部集合...但是這會比我想寫的SO回答更復雜一點....至少現在。 –