すでにBaseStreamに関して作られたポイントは、有効かつ重要です。しかし、テキストを読んで、テキストのどこにいるかを知りたいという状況があります。再利用を容易にするためのクラスとして書くことは依然として有効です。
私はそのようなクラスを今書きました。それは正しく動作するようですが、それはむしろ遅いです。パフォーマンスが重要ではない場合は、それは問題ありません(で、が遅い、下記を参照)。
一度に1つの文字、一度に1つのバッファ、または一度に1つの行を読み込んでも、同じロジックを使用してテキストの位置を追跡します。これを放棄することで、これをより良く実行することができると確信していますが、実装するのがずっと簡単になりました。コードを守ることを願っています。
私はReadLineメソッド(この実装の最も弱い点だと思います)とStreamReaderの非常に基本的なパフォーマンス比較を行いました。その違いはほぼ桁違いです。私はクラスStreamReaderExを使って22 MB/sを得ましたが、StreamReaderを直接使って(SSDを搭載したラップトップでは)ほぼ9倍でした。面白いかもしれませんが、私は適切な読書テストをする方法を知らない。多分ディスクバッファよりも大きい2つの同一のファイルを使用して、それらを交互に読みます。少なくとも私の単純なテストでは、何回か実行すると一貫した結果が得られ、どのクラスがテストファイルを最初に読み込んでも問題はありません。
デフォルトでは、NewLineシンボルはEnvironment.NewLineに設定されますが、長さが1または2の任意の文字列に設定することができます。リーダーはこのシンボルのみを改行と見なします。少なくとも私は、Visual Studioが私に開いたファイルに「改行が矛盾している」というかなりの回数のメッセージを表示していることを知っています。
Guardクラスは含まれていません。これはシンプルなユーティリティクラスであり、コンテキストからオブジェクトを置き換える方法はobvoiusでなければなりません。あなたはそれを削除することもできますが、引数のチェックを失うことになり、結果として得られるコードは "正しい"ものから遠くなるでしょう。たとえば、Guard.NotNull(s、 "s")は、sがnullでないかどうかを単純にチェックし、ArgumentNullException(引数名 "s"、したがって2番目のパラメータ)を投げます。
十分なせせらぎ、ここでのコードは次のとおりです。
public class StreamReaderEx : StreamReader
{
// NewLine characters (magic value -1: "not used").
int newLine1, newLine2;
// The last character read was the first character of the NewLine symbol AND we are using a two-character symbol.
bool insideNewLine;
// StringBuilder used for ReadLine implementation.
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);
}
public string NewLine
{
get { return "" + (char)newLine1 + (char)newLine2; }
private set
{
Guard.NotNull(value, "value");
Guard.Range(value.Length, 1, 2, "Only 1 to 2 character NewLine symbols are supported.");
newLine1 = value[0];
newLine2 = (value.Length == 2 ? value[1] : -1);
}
}
public int LineNumber { get; private set; }
public int LinePosition { get; private set; }
public override int Read()
{
int next = base.Read();
trackTextPosition(next);
return next;
}
public override int Read(char[] buffer, int index, int count)
{
int n = base.Read(buffer, index, count);
for (int i = 0; i
これは 'Seek'の使用についても説明していません。 –