2016-07-13 12 views
0

GBファイルのために一度に10本以上の行を読み込んで処理したいが、最後まで10行を吐き出す解決法は見つかっていない。一度にファイルのx行数を読む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行もあなたを永遠に連れていくでしょう。たとえば このリンクをチェックしてください - 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

デフォルトの動作は、1ショットですべての行を読み込むことです。読み込み方法を少し深く掘り下げて読み取る必要がある場合は、StreamReaderを取得して読み取りプロセスを制御できるようにします

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

それはまた、あなたがConcurrentBagでこれらのタスクが含まれている場合は、非常に簡単に一度に10行で実行している処理を続けることができますタスク

を返しますReadLineAsync方法があります。

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 
     } 
    } 
} 

このコードは参考用であり、

あなたが望むすべては最後の10行であるならば、あなたはこの方法では、あなたのファイルからの行の「ページ」を作成することになり、ここで How to read a text file reversely with iterator in C#

+1

'' read 'を待つ必要はなく、readは完了した状態であることを保証します(匿名メソッドが非同期とマークされていないためコンパイルもされません)。ただ '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

.Netが最大2Gbのメモリページサイズを持っていることが完全にはわかりません。マルチGbの場合は、その制限を非常に速く打ちます。 – MikeT

+0

呼び出した分だけメモリに読み込まれます。 '.AsParallel()。WithDegreeOfParallelism(n))'のようなものを使用している場合、指定された時間に読み込まれるのはnページだけです。 –

+0

はい、IEnumerableのインナーセットでさえ、もっと怠け者にすることは可能でしょう...しかし、それは私がSO答えを書きたいと思うより少し複雑です....少なくとも今は。 –

関連する問題