我写了一个非常简单的C#类来读取UTF8文件的所有字符。
对于主循环,检测文件结尾的条件是:
while (!fin.EndOfStream)
{
int c = fin.Read();
<some text processing>
}
但我至少知道另外两种方法:
while (fin.Peek() >= 0)
{
int c = fin.Read();
<some text processing>
}
和
int c = 0;
while ((c = fin.Read()) >= 0)
{
<some text processing>
}
对我来说,第一种形式是最好的:更短,更清晰,条件很容易理解,当你到达结束时你不必知道Read()或Peek()返回-1文件。
除了第二和第三种形式不遵循信息隐藏原则(维基百科引用): Information Hiding principle.
我的问题是:
为什么有这么多方法来检查文件的结尾?
为什么花时间和资源设计,编码,测试和维护这么多方法来检查文件的结尾?
编辑:
Read and Peek警告你文件的结尾,你可以用它们来完成EndOfStream的工作。我的意思是:Read和Peek正在做他们自己的工作和EndOfStream的工作,所以Read和Peek正在做更多他们的名字建议的工作。每当到达文件末尾时,都可以使用异常而不是整数。
答案 0 :(得分:2)
你的问题的前提是错误的。
所有这些功能都有不同的语义,不同的目的。仅仅因为它们在一个上下文中是可互换的,并不意味着您可以在每种情况下自由地进行。其中只有一种方法专门用于检查流的结尾 - fin.EndOfStream
。
仅仅因为人们使用棒球棒击打其他人,这并不意味着棒球棒是多余的和无用的,因为还有其他(甚至更好)的方法。它们的目的在不同的背景下。
实际上可能会争论(至少在我看来),fin.EndOfStream
可能是(fin.Peek() >= 0)
多余的,或者语言设计者可能做到这一点,但是他们决定允许程序在语义上清洁。检查流的结尾感觉比下一个预期出错的字符更自然。
您谈论的每种方法和财产的存在都是合理的。
答案 1 :(得分:0)
Peek
等于Read
而不影响流的状态,因此我不会将其视为“替代”。还有一些其他类提供Peek
和Read
选项。
还有其他类使用Read
来读取和通知流的结尾,XmlReader
例如返回bool
而不是数字。
我同意你的意见,使用号码作为指示是否到达终点是奇数。顺便说一下,流末尾的Read
的返回值是0,而不是-1,当数据不可用尚时,流被记录为阻塞,直到数据可用(因为如果它返回0,则意味着流的结束)。他们本可以选择bool TryRead(..., out int bytes)
。
我不知道如何做出有关Stream
的决定,但如果它满足了您的问题,我们可以假装他们完全按照您的意思行事,并为那些没有做过的人{39}创建了EndOfStream
财产; t喜欢其他方法。一种证据就是Stream
的实施者不必实施EndOfStream
,因为它只代表最后一次Read
操作的状态。