BaseStreamに関してすでに述べた点は、有効で重要です。ただし、テキストを読み、テキストのどこにいるかを知りたい場合があります。再利用を容易にするために、それをクラスとして作成することは依然として有用です。
私は今、そのようなクラスを書こうとしました。正しく動作しているように見えますが、かなり遅いです。パフォーマンスが重要でない場合は問題ないはずです(それほど遅くはありません。以下を参照してください)。
一度にcharを読み取るか、一度に1つのバッファーを読み取るか、または一度に1行を読み取るかに関係なく、同じロジックを使用してテキスト内の位置を追跡します。これを放棄することで、パフォーマンスをかなり向上させることができると確信していますが、実装がはるかに簡単になりました...そして、コードに従うことを願っています。
ReadLineメソッド(この実装の最も弱い点であると私は信じています)とStreamReaderの非常に基本的なパフォーマンス比較を行いましたが、その違いはほぼ1桁です。クラスStreamReaderExを使用して22MB/秒を取得しましたが、StreamReaderを直接(SSDを搭載したラップトップで)使用すると約9倍になります。面白いかもしれませんが、適切な読解テストを行う方法がわかりません。おそらく、それぞれがディスクバッファよりも大きい、2つの同一のファイルを使用し、それらを交互に読み取ります。少なくとも私の単純なテストは、それを数回実行すると、どのクラスが最初にテストファイルを読み取るかに関係なく、一貫した結果を生成します。
NewLineシンボルのデフォルトはEnvironment.NewLineですが、長さ1または2の任意の文字列に設定できます。読者はこのシンボルのみを改行と見なします。これは欠点となる可能性があります。少なくとも、Visual Studioによって、開いたファイルに「一貫性のない改行がある」というかなりの回数のプロンプトが表示されたことはわかっています。
Guardクラスは含まれていないことに注意してください。これは単純なユーティリティクラスであり、それを置き換える方法のコンテキストからはわかりにくいはずです。それを削除することもできますが、引数のチェックが失われるため、結果のコードは「正しい」とはほど遠いものになります。たとえば、Guard.NotNull(s、 "s")は、sがnullでないことを単にチェックし、その場合はArgumentNullException(引数名 "s"、したがって2番目のパラメーター)をスローします。
十分なせせらぎ、ここにコードがあります:
パブリッククラスStreamReaderEx:StreamReader
{{
//改行文字(魔法の値-1:「未使用」)。
int newLine1、newLine2;
//最後に読み取られた文字は、改行記号の最初の文字であり、2文字の記号を使用しています。
bool insideNewLine;
//ReadLineの実装に使用されるStringBuilder。
StringBuilder lineBuilder = new StringBuilder();
public StreamReaderEx(string path、string newLine = "\ r \ n"):base(path)
{{
init(newLine);
}
public StreamReaderEx(Stream s、string newLine = "\ r \ n"):base(s)
{{
init(newLine);
}
パブリック文字列改行
{{
get {return "" +(char)newLine1 +(char)newLine2; }
プライベートセット
{{
Guard.NotNull(value、 "value");
Guard.Range(value.Length、1、2、 "1〜2文字の改行記号のみがサポートされています。");
newLine1 = value [0];
newLine2 =(value.Length == 2?value [1]:-1);
}
}
public int LineNumber {get; プライベートセット; }
public int LinePosition {get; プライベートセット; }
public override int Read()
{{
int next = base.Read();
trackTextPosition(next);
次に戻る;
}
public override int Read(char [] buffer、int index、int count)
{{
int n = base.Read(buffer、index、count);
for(int i = 0; i