Read(char []、int、int)が要求されたすべての文字を返すのに失敗し、ReadBlock()が期待どおりにすべての文字を返す状況を知りたいです(たとえば、StreamReaderがFileStreamオブジェクトのインスタンスで動作する場合)。
2 に答える
実際には、を使用する場合StreamReader
、しばらく遅延する可能性のあるストリームでのみ発生する可能性があります。たとえば、ここで言及されているネットワーク ストリームなどです。
ただし、TextReader
一般的には、いつでも発生することが予想されます (.NET の将来のバージョンでは、現在発生していない可能性があります。StreamReader
バックアップされている場合は発生しないことFileStream
は文書化されていません。したがって、今後発生しないという保証はありません)。
特に、現在のバッファを空にするだけで呼び出しを部分的に満たすことができる場合、実装者が要求された量を返さない方が簡単な場合が多くあります (よりシンプルで信頼性が高く、おそらくより効率的なコードの影響により)。 、またはTextReader
より少ない文字数しか返せない操作を実行する前に、バッキングソース (ストリームまたは別の ) に渡す量として要求された量を使用することによって。
ここで、「いつ StreamReader.ReadBlock() を使用するか」という実際の質問に答えます。(または、より一般的には、いつ TextReader.ReadBlock() を使用するか)。次の点に注意してください。
Read()
ソース全体が読み取られない限り、との両方ReadBlock()
が少なくとも 1 文字を返すことが保証されます。保留中のコンテンツがある場合、どちらも 0 を返しません。ReadBlock()
不必要にループするので、いつでも呼び出すRead()
のは無駄です。しかし一方で、それほど無駄ではありません。
しかし、第 3 に、
Read()
要求された文字数よりも少ない文字数を返すケースは、多くの場合、別のスレッドが次の呼び出しのバッファを満たすコンテンツの取得に関与している場合、またはそのコンテンツがまだ存在しない場合 (ユーザー入力など) です。または別のマシンでの保留中の操作) - 部分的な結果を処理し、それRead()
が終了したときに再度呼び出すことで、全体的な同時実行性が向上します。
そう。部分的な結果で何か役に立つことができる場合は、呼び出しRead()
て、得られたものに取り組みます。特に、ループしてそれぞれの結果に取り組んでいるRead()
場合は、 ではなくこれを実行してくださいReadBlock()
。
注目すべきケースは、別のものに支えられた独自の TextReader を構築している場合です。ReadBlock()
アルゴリズムが機能するために特定の文字数が実際に必要でない限り、呼び出す意味はありません。呼び出しからできるだけ多くを返し、必要に応じてRead()
呼び出し元のコードを呼び出させるReadBlock()
だけです。
特に、次のコードに注意してください。
char buffer = char[4096];
int len = 0;
while((len = tr.ReadBlock(buffer, 0 , 4096)) != 0)
DoSomething(buffer, 0, len);
次のように書き換えることができます。
char buffer = char[4096];
for(int len = tr.Read(buffer, 0, 4096); len != 0; len = tr.Read(buffer, 0, 4096))
DoSomething(buffer, 0, len);
より小さなサイズで呼び出すDoSomething()
こともありますが、次の呼び出しにデータを提供するために別のスレッドが関与している場合は、同時実行性が向上する可能性がありますRead()
。
ただし、ほとんどの場合、ゲインは大きくありません。特定の文字数が本当に必要な場合は、 を呼び出してReadBlock()
ください。最も重要なことは、 が実行したことを確認するオーバーヘッドが非常にわずかRead()
であるため、同じ結果が得られる場合です。特定のケースで安全かどうかを推測しようとしないでください。の保証が必要な場合は、を使用してください。ReadBlock()
ReadBlock()
Read()
ReadBlock()
ReadBlock()
これは、ネットワーク ストリームの大きな問題です。特に、ストリーム データが非常に大きく、ストリームを提供するサーバーがチャンク出力 (つまり、HTTP では非常に一般的) として実行する場合はRead()
、EOS が読み込まれると、単一の文字の読み取りで -1 が返されるためです。 EOS に到達した場合は、引数を指定して を呼び出し、要求Read(char[], int, int)
された文字数まで取得し、EOS に到達した場合は読み取った文字数を返し、EOS に到達した場合は 0 を返します。
ストリームReadBlock()
からデータが利用可能になるのを待つため、この問題に遭遇することはありません。
注意すべきもう 1 つの点は、両方のフォームが最大文字数を読み取ることであり、使用可能な文字数がそれほど多くない場合、その数の文字が返されるとは限りません。
少し前に同様のトピックについて質問しました - HttpResponseStream からの読み取りに失敗しました- HTTP ストリームからの読み取りに問題があったとき