我想知道一种情况Read(char [],int,int)无法返回请求的所有字符,而ReadBlock()按预期返回所有字符(例如当StreamReader使用FileStream对象的实例时)。
答案 0 :(得分:15)
在实践中,当使用StreamReader
时,只会发生可能会延迟一段时间的流 - 例如人们在这里提到的网络流。
但是,通常使用TextReader
,您可以预期它会在任何时候发生(包括可能在未来版本的.NET中发生,如果它当前没有发生 - 它不会发生StreamReader
支持FileStream
的情况未记录在案,因此无法保证将来不会发生此事。)
特别是在很多情况下,如果实施者只需清空就可以部分完成呼叫,那么实施者就不会返回请求的数量,这样做更容易(通过更简单,更可靠,可能更有效的代码)当前缓冲区,或者在执行只能返回较少字符数的操作之前,使用请求的金额作为传递给后备源(流或其他TextReader
)的数量。
现在,回答关于“何时使用StreamReader.ReadBlock()的实际问题?” (或者更一般地,何时使用TextReader.ReadBlock())。应牢记以下几点:
除非已读取整个源,否则Read()
和ReadBlock()
都保证至少返回一个字符。如果有待处理的内容,也不会返回0.
在ReadBlock()
执行时调用Read()
是浪费的,因为它不必要地循环。
但另一方面,不浪费。
但是在第三方面,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()
。
答案 1 :(得分:-1)
这是网络流上的一个主要问题,特别是如果流数据非常大并且提供流的服务器就像分块输出那样(即非常典型的HTTP),因为只调用Read()
即单个字符一旦达到EOS,read给出-1,带有参数的Read(char[], int, int)
的调用达到要求的字符数或更少,如果达到EOS则返回,如果EOS已经过,则返回读取的字符数或零达到
ReadBlock()
等待数据从流中获取,因此您永远不会遇到此问题。
另外需要注意的是,两个表单都会读取最大字符数,如果没有那么多字符,则无法保证返回那么多字符
前段时间我问了一个关于类似主题的问题 - Reading from a HttpResponseStream fails - 当我从HTTP流中读取问题时