8

テキストリーダーを使用している場合、実際にデータの最後にいることを検出するための最良の方法は何ですか?これを行う通常の方法は、次のようなものです。

    while(reader.Peek() != -1)
    {
       ///do stuff
    }

ただし、ここのmsdnドキュメントには次のように記載されています

次に読み取る文字を表す整数。使用可能な文字がなくなった場合、またはリーダーがシークをサポートしていない場合は-1。

だから私の質問は、あなたが本当にリーダーデータの最後にいるのか、それともリーダー/基になるストリームがここでの戻り値があいまいなように見えるのでシークをサポートしていないのかをどうやって見分けるのですか?たとえば、私が以下を持っている場合

    public void Parse(TextReader reader)
    {
         while(reader.Peek() != -1) //am I really at the end
         {
            //do stuff
         }
    }

    Parse(new StreamReader(new NetworkStream(....)));

networkstreamはシークをサポートしていないため。

それとも私は何かを逃したことがありますか?

編集:

明確にするために、EoSをチェックできるので、より具体的なStreamReaderクラスを使用してこれを簡単に実装できます。ただし、より一般的なものにするために、私はTextReaderを使用したかったので、StreamReaderだけに縛られることはありません。ただし、Peekのセマンティクスは少し奇妙に思えます。シークがサポートされていない場合にスローしないのはなぜですか。また、この目的のために、TextReaderのEoFプロパティがないのはなぜですか。

4

4 に答える 4

5

Peek() を使用して特定の値を探している場合を除き、.Read() を使用しないのはなぜですか

例えば

string line;
System.IO.StreamReader file = new System.IO.StreamReader(strfn);
while((line = file.ReadLine()) != null)
{
  this.richTextBox1.AppendText(line+"\n");//you can replace this line to fit your UseCase
}

これがどのように行われるかのよりクリーンな例が必要な場合は、以下に投稿したようなものを読みやすくすることができ、独自のテキストファイルの値をプラグインしてこれをデバッグして、それが機能することを確認できます。読み書き

string tempFile = Path.GetTempFileName();
using(var sr = new StreamReader("file.txt"))
{
  using(var sw = new StreamWriter(tempFile))
  {
    string line;
    while((line = sr.ReadLine()) != null)
    {
         if(line != "BlaBlaBla")
             sw.WriteLine(line);
    }
  }
}

ここにあなたが試すことができる別のオプションがあります

から、非正の結果が得られる場合とStream、負の結果が得られる場合。Read(buffer, offset, count)Peek()

を使用するBinaryReader、ドキュメントPeekChar()はそれが負を返す必要があることを示唆しています:

戻り値

型: System.Int32 次に使用可能な文字。使用可能な文字がそれ以上ない場合、またはストリームがシークをサポートしていない場合は -1。

これは破損したストリームではありませんか? つまり、残りのデータは、指定さcharれたエンコーディングから完全なものを形成できませんか?

于 2012-11-30T18:12:30.423 に答える
4

これはreader.Read()==-1である必要があります。これ以上文字は存在しません。

于 2012-11-30T18:06:42.287 に答える
4

それは本当に解析で何をしているかに依存します。

私は通常、ただRead, どれだけ読まれているかを確認します. ただし、一度に文字を読まないことをお勧めします。

char[] buffer = new char[1024 * 16];
int charsRead;
while ((charsRead = read.Read(buffer, 0, buffer.Length)) > 0)
{
    // Process buffer, only as far as charsRead
}
于 2012-12-01T09:02:05.900 に答える
0

ストリームの最後まですべてのデータを読み取って処理する必要があるだけの場合は、Read直接使用する必要があります。使用できる文字がなくなると、-1 が返されます。

int nextByte;
while ((nextByte = reader.ReadByte()) != -1)
    // Process nextByte here.

編集:リーダーがシークをサポートしているかどうかを具体的に確認する別の方法は、基になるストリームを確認することです。

bool canSeek = reader.BaseStream.CanSeek;

これが を返す場合truePeekストリームの最後に達したときにのみ -1 を返す必要があります。

于 2012-11-30T18:11:46.487 に答える