2010-10-07 85 views
5

std::istream有原型istream& read (char* s, streamsize n)实际读取的字节数应通过调用istream::gcount(),也istream的有效性可以从ios::good知道来得到。了解的std :: istream的设计::阅读

我正在讨论另一个流类的实现,我试图和我的一个同事一起写,我在说我可能会遵循这个设计;但他表示,不要每次都有用户致电gcount,否则可能会看到像istream& read (char* s, streamsize n, size_t &bytes_read)这样的原型,所以它会在一次通话中结束,前者更笨拙。我无法防守std的设计选择。 istream::read背后的真正理由是什么?

+0

你的意思是'size_t&bytes_written'吗?而且,它应该是'streamsize&bytes_written'(或者'chars_read')。 – 2010-10-07 14:22:39

+0

@詹姆斯:是的,谢谢!字节和字符是同义词_here_,因为'sizeof'是相同的:) – legends2k 2010-10-07 14:43:48

回答

4

我认为这是因为C++通常不会强制所有人都不需要的接口。如果您需要read接受某些人不关心的参数,那么它会导致额外的编码工作(声明一个额外的int作为参数传递)。无论客户端是否在意,它也总是保存读取的字节数(某些客户端可能会在意eof/fail位指示的读取失败)。

使用单独的方法,您可以为可能需要或不需要的不同信息的接口分离接口。

0

std::istream有原型 istream& read (char* s, streamsize n)实际读取的字节数 应通过调用 istream::gcount(),还有效性的istream的 可以从 ios::good知道来得到。

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数组中第一个元素的大小。

+0

@CashCow对'istream :: read'的局限性有正确的解决方案。我无法赞成,因为我没有至少15点的声望(我仍然是Stack Overflow n00b)。 – 2010-10-11 15:58:12

+0

我的实际问题是,为什么我们需要调用'gcount';相反,为什么没有它像调用者可以传递一个refernce变量,它将由'read'设置为实际读取的字节数(可以小于或等于'streamsize n'),而不是调用者调用gcount每次。 – legends2k 2010-10-13 13:14:21

+0

用'istream :: readsome'解释@CashCow读取的字节数似乎更可取。正如@Mark B所解释的,它避免了必须声明一个额外的int来通过引用传递。另一种选择是将指针传递给默认为NULL的变量,该变量可用于忽略读取的实际字节数:'istream&read(char * s,streamsize n,streamsize * bytesRead = NULL)'。但是,我不知道它是否会比'istream :: readsome'提供显着的优势。 – 2010-10-13 13:42:02

2

尝试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); 
0

在回答原来的问题,有错误检查调用的是一种流行的编程风格当C是年轻的,但它很快就熄灭了时尚的后。发生的事情是那些没有错误的小事情,但是在一段时间之后,它们几乎总是存在一些劣势,直到它们被社区叫出来并被贴上坏标签。这个代码有一个不幸之处,那就是在广泛讨论这个小反模式之前写了这个代码。

为了回应Cash Cow的解决方案,我认为存在一个错误。如果您在IO上等待并且有足够的字符来部分填充缓冲区,那么该函数将返回并且while循环将在文件被完全读取之前结束。所以如果在直接原始IO上写入,他的解决方案可能会正确运行,但是会在缓冲IO上运行失败。

当然,正确的解决方案是在设置EOF标志时结束while循环。目前我还不确定什么时候最好的反应是什么时候设置了badbit,但你也应该处理这种情况。

虽然,我会同意readsome是一个体面的替代阅读。

编辑: 有时读取不可用(一些VC++版本)。在这种情况下,读取不可用。