Stream上的默认实现创建一个新的单字节数组,然后调用Read。虽然这是正式的,但效率低下。任何具有内部缓冲区的流都应该重写此方法,并提供一个更高效的版本,直接读取缓冲区,避免每次调用时额外的数组分配。
取自FileStream.ReadByte文档:
http://msdn.microsoft.com/en-us/library/system.io.filestream.readbyte.aspx
这是什么,以及如何克服这种低效率?
答案 0 :(得分:4)
嗯,意思似乎相当清楚 - 解决方法就是不要拨打ReadByte
。
不要一次读取一个字节 - 使用Read(byte[], int, int)
方法读入适当大小的缓冲区(我通常大约8K,但大约那个数量级的任何东西应该没问题)。如果您需要在此之后单独读取字节,请从缓冲区中一次读取一个。
如果您需要确保读取的内容超出了您的意图,如果您看到我的意思,那么这就成了一个问题 - 例如,如果您不打算读取前0个字节,因为这意味着它是下一个“消息”的开始,并且您希望以后能够再次阅读。理想情况下,避免将自己设计成这种情况。
在这种情况下,在FileStream
中包含BufferedStream
可能有所帮助,但如果重要的话,我会仔细衡量一下这些表现......并且仍然会尽量避免设计如果你能提供帮助,则需要一次读取一个字节。
答案 1 :(得分:3)
您需要使用Read
方法来读取缓冲区。读单字节效率不高。使用缓冲区:
byte[] buffer = new byte[4096]; // 4K
int bytesRead =0;
while((bytesRead = stream.Read(buffer, 0, buffer.Length))>0)
{
// Do whatever with buffer
}
答案 2 :(得分:3)
当您从Stream
继承时,这只是一个值得关注的问题。执行此操作时,您必须至少提供Read
方法,ReadByte
在基类中实现。ReadByte
。这很好,但是当你的流能够直接获取单个字节时效率很低 - 默认实现将首先在内部创建一个单字节缓冲区,将其传递给Read
以填充它,然后返回单个字节。如果你可以实现你的缓冲区,以便可以直接返回单个字节,而不需要分配临时缓冲区,你应该这样做。
对于调用代码,唯一的考虑因素是,当您需要读取字节只是为了将它们存储在缓冲区中时,ReadByte
通常比ReadByte
更有效,即使您只是在阅读单个字节 - 但如果您真的只需要一个字节,并且您使用的流实现提供了优化版本,ReadByte
实际上可能更快。如果您读取单个字节以便立即处理,ReadByte
根本不应该成为问题 - 毕竟,大多数标准流类已经缓冲,应该提供优化的{{1}}。如有疑问,请参阅。
答案 3 :(得分:2)
我在使用FileStream
ReadByte()
方法时未发现任何问题。
我认为文档实际上令人困惑。
抽象Stream类实现的ReadByte()
方法效率低下,因为它"创建一个新的单字节数组,然后调用Read()
"。
但是,由FileStream实现的ReadByte()
的重写版本通过直接读取内部缓冲区来听取此警告的建议,如您在源here中看到的那样。因此,我们不清楚为什么FileStream
ReadByte()
的文档会对此警告产生影响。
答案 4 :(得分:1)