理解 std::istream::read 的设计
std::istream
具有原型 istream& read (char* s, Streamsize n)
读取的实际字节数应通过调用istream::gcount()
获得,同时也是读取的有效性istream
可以从ios::good
得知。
我当时正在与我的一位同事讨论我试图编写的另一个流类的实现,我当时说我可能会遵循这种设计;但他说,与其让用户每次都调用 gcount,不如像这样 istream& 那样读取原型。 read (char* s, Streamsize n, size_t &bytes_read)
这样它就会在一次调用中完成,而前者更笨拙。我无法捍卫 std
的设计选择。 istream::read 背后的真正原理是什么?
std::istream
has the prototype istream& read (char* s, streamsize n)
the actual number of bytes read should be gotten by calling istream::gcount()
, also the validity of the istream
can be known from ios::good
.
I was discussing another stream class' implementation I was trying to write with a colleague of mine, where I was saying I might follow this design; but he said instead of having the user call gcount everytime, one could have read's prototype like this istream& read (char* s, streamsize n, size_t &bytes_read)
so that it'll get over in a single call and the former is clumsier. I was unable to defend std
's design choice. What's the real rationale behind istream::read
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为这是因为 C++ 通常不会强制使用可能不是每个人都需要的接口。如果您需要 read 来接受一些人不关心的参数,那么它会导致额外的编码工作(声明一个额外的 int 作为参数传递)。它还始终保存读取的字节,无论客户端是否关心(某些客户端可能只关心 eof/fail 位指示的读取失败)。
使用单独的方法,您可以将可能需要或不需要的不同信息的接口解耦。
I assume it's because C++ doesn't typically force an interface that may not be needed by everyone. If you require
read
to accept a parameter that some people don't care about, then it causes extra coding work (declaring an extra int to pass as a parameter). It also always saves the bytes read regardless of whether the client cares or not (some clients may just care that the read failed as indicated by the eof/fail bits).With a separate method you de-couple the interface for different pieces of information that may or may not be needed.
请尝试使用 readsome 命令,
buf 是您的缓冲区,num 是您希望读取的字节数,当然,最多是缓冲区中可用的字节数。
返回值是实际读取的字节数。
要读取文件末尾,您可以循环:
Try the readsome command instead,
buf is your buffer and num is the number of bytes you wish to read, at most the number of bytes available in your buffer, of course.
The return value is the number of bytes actually read.
To read a file to the end you can loop:
istream::read(char* s, Streamsize n)
将大小为n
的未格式化数据块(没有NULL
终止符)读取到数组中在s
。尽管s
是指向char
的指针,您也可以使用istream::read
来读取二进制数据。例如,您可以有一个istream
来保存双精度数组的值(假设字节顺序是正确的):istream::gcount()
返回最后一次调用 istream::read 时读取的字节数。在这种情况下,我们看到count
的大小可能与double
的大小不同,因此我们无法使用istream::gcount ()
指定data
数组中第一个元素的大小。istream::read(char* s, streamsize n)
reads an unformatted block of data (withoutNULL
termination) of sizen
into the array ats
. Even thoughs
is a pointer tochar
, you can useistream::read
to read binary data. For example, you could have anistream
that holds the values of an array of doubles (assuming that the endianness is correct):istream::gcount()
returns the number of bytes read in the lastistream::read
call. In this case, we see that the size ofcount
is probably different from the size of adouble
, therefore we would not be able to useistream::gcount()
to specify the size of the first element in thedata
array.回答最初的问题时,错误检查调用是 C 年轻时一种流行的编程风格,但很快就过时了。发生的事情都是一些小事情,虽然不是很错,但几乎总是有点低劣,会存在一段时间,直到被社区指出并贴上坏的标签。不幸的是,这段代码是在广泛讨论这个小反模式之前编写的。
针对Cash Cow的解决方案,我认为有一个bug。如果您正在等待 IO 并且有足够的字符来部分填充缓冲区,则该函数将返回,并且 while 循环将在文件完全读取之前结束。因此,如果在直接原始 IO 之上编写,他的解决方案可能会正确运行,但在缓冲 IO 上运行会失败。
当然,正确的解决方案是在设置 EOF 标志时结束 while 循环。我目前不确定设置 badbit 时的最佳响应是什么,但您可能也应该处理这种情况。
不过,我同意 readsome 是一个不错的阅读替代方案。
编辑:
有时 readsome 不可用(某些 VC++ 版本)。在这种情况下,read也不是不能用。
In response to the original question, having error check calls was a popular programming style when C was young, but it went out of vogue soon after. What happens is little things that are not very wrong, but nevertheless are almost always just a little inferior exist for a while until they are called out and labeled as bad by the community. This code has the misfortune of having been written before that little anti-pattern was widely discussed.
In response to Cash Cow's solution, I think there is a bug. If you are waiting on IO and have enough chars to partially fill the buffer, then the function will return and the while loop will end before the file is completely read. So his solution would probably run correctly if written on top of straight raw IO, but would fail running over buffered IO.
The correct solution, of course, would be to end the while loop when the EOF flag is set. I am not sure at the moment what the best response is when badbit is set, but you should probably handle that case too.
I would agree that readsome is a decent alternative to read, though.
Edit:
Sometimes readsome is not available (some VC++ versions). In this case, read is not unusable.