理解 std::istream::read 的设计

发布于 2024-09-26 16:06:10 字数 459 浏览 5 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

隐诗 2024-10-03 16:06:10

我认为这是因为 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.

清秋悲枫 2024-10-03 16:06:10

请尝试使用 readsome 命令,

streamsize readsome ( char* buf, streamsize num );

buf 是您的缓冲区,num 是您希望读取的字节数,当然,最多是缓冲区中可用的字节数。

返回值是实际读取的字节数。

要读取文件末尾,您可以循环:

char buf[BUF_SIZE]
streamsize bytesRead;
do
{
   bytesRead = instr.readsome( buf, BUF_SIZE );
   // do stuff with the bytes you read, if any
} while ( bytesRead == BUF_SIZE );

Try the readsome command instead,

streamsize readsome ( char* buf, streamsize num );

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:

char buf[BUF_SIZE]
streamsize bytesRead;
do
{
   bytesRead = instr.readsome( buf, BUF_SIZE );
   // do stuff with the bytes you read, if any
} while ( bytesRead == BUF_SIZE );
东京女 2024-10-03 16:06:10

std::istream 有原型
istream&读取(字符* s,流大小n)
读取的实际字节数
应该通过调用获得
istream::gcount(),也是有效性
istream 可以从
ios::好。

istream::read(char* s, Streamsize n) 将大小为 n 的未格式化数据块(没有 NULL 终止符)读取到数组中在s。尽管s是指向char的指针,您也可以使用istream::read来读取二进制数据。例如,您可以有一个 istream 来保存双精度数组的值(假设字节顺序是正确的):

unsigned int count;
input.read(reinterpret_cast<char*>(&count), sizeof(count));
double* data = new double[count];

for (unsigned int i = 0; i < count; ++i)
    input.read(reinterpret_cast<char*>(data[i]), sizeof(double));

istream::gcount() 返回最后一次调用 istream::read 时读取的字节数。在这种情况下,我们看到 count 的大小可能与 double 的大小不同,因此我们无法使用 istream::gcount () 指定 data 数组中第一个元素的大小。

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.

istream::read(char* s, streamsize n) reads an unformatted block of data (without NULL termination) of size n into the array at s. Even though s is a pointer to char, you can use istream::read to read binary data. For example, you could have an istream that holds the values of an array of doubles (assuming that the endianness is correct):

unsigned int count;
input.read(reinterpret_cast<char*>(&count), sizeof(count));
double* data = new double[count];

for (unsigned int i = 0; i < count; ++i)
    input.read(reinterpret_cast<char*>(data[i]), sizeof(double));

istream::gcount() returns the number of bytes read in the last istream::read call. In this case, we see that the size of count is probably different from the size of a double, therefore we would not be able to use istream::gcount() to specify the size of the first element in the data array.

衣神在巴黎 2024-10-03 16:06:10

回答最初的问题时,错误检查调用是 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文