使用xsputn和overflow继承ostream和streambuf问题

时间:2011-04-12 21:52:17

标签: c++ iostream ostream streambuf

我一直在研究创建自己的ostream以及一个streambuf来处理我的ostream的缓冲区。我实际上大部分工作,我可以插入(<<)到我的流并获得字符串没有问题。我通过虚拟函数xsputn来实现这一点。但是,如果我向流输入(<<<&)一个浮点数或一个int而不是字符串xsputn永远不会被调用。

我已经遍历了代码,我看到流正在调用do_put,然后是f_put,它最终会尝试将float 1字符一次放入缓冲区。我可以让它调用我的虚函数溢出(int c)的实现,如果我让我的缓冲区没有空格,从而得到浮点数和int的数据。

现在问题就在这里,我需要知道何时将float放入缓冲区。换句话说,我需要知道这是什么时候最后一次溢出将被调用一个特定的值流入.xsputn对我有用的原因是因为我得到了整个值及其长度。所以我可以将它复制到缓冲区然后调用等待缓冲区已满的函数。

我无可否认地滥用了ostream设计,因为我需要缓存输出,然后对每个输入值(<<<<<<<<<<<<<<

无论如何要清楚我会以另一种方式重申我正在拍摄的内容。我很有可能以错误的方式解决这个问题。

我想使用继承的ostream和streambuf所以我可以输入值并允许它为我处理我的类型转换,然后我想将这些信息传递给另一个对象,我将句柄传递给streambuf到(for?)。该对象有昂贵的i / o所以我不想一次发送数据1个字符。

如果不清楚,请提前抱歉。谢谢你的时间。

1 个答案:

答案 0 :(得分:16)

虽然听起来很粗糙,但你做的不太清楚 对。只是为了确定:您提供的所有ostream都是 便利构造函数来创建和安装streambuf, 析构函数,可能是rdbuf的实现 处理正确类型的缓冲区。假设这是真的: 在xsputn中定义streambuf纯粹是一种优化。 您必须定义的关键功能是overflow。最简单的 overflow的实现只需要一个字符,并且 将其输出到接收器。除此之外的一切都是优化: 例如,您可以使用setp设置缓冲区;如果你这样做 这样,只有当缓冲区被调用时才会调用overflow 已满,或请求同花。在这种情况下,你必须 输出缓冲区也是如此(使用pbasepptr来获取 地址)。 (streambuf基类初始化 用于创建0长度缓冲区的指针,因此overflow将是。imbue 呼唤每个角色。)你可能会做的其他功能 想要覆盖(非常)特定情况:

setbuf:如果出于某种原因需要语言环境。 (记住这一点 当前字符编码是语言环境的一部分。)

seekoff:允许客户端代码指定缓冲区。 (恕我直言,是的 通常不值得打扰,但你可能有特殊之处 要求。)

streambuf:支持寻求。我从来没有在任何一个中使用过它 我的sync,所以除了什么之外我不能提供任何信息 你可以阅读标准。

setp:在flush上调用,应输出中的任何字符 缓冲到水槽。如果你从不打电话给overflow(所以没有 缓冲区),你总是在同步,这可能是一个无操作。 uflowsync可以拨打此电话,或者两者都可以拨打电话 单独的功能。 (关于uflow之间的唯一区别 而uflow只有sync才会被调用 一个缓冲区,如果缓冲区为空,它将永远不会被调用。 如果客户端代码刷新流,则将调用overflow。)

编写自己的流时,除非性能要求 否则,我会保持简单,只覆盖write(address, length)。 如果性能指示缓冲区,我通常会将代码放入 将缓冲区刷新为单独的overflow 功能,并实现syncint MyStreambuf::overflow( int ch ) { if ( pbase() == NULL ) { // save one char for next overflow: setp( buffer, buffer + bufferSize - 1 ); if ( ch != EOF ) { ch = sputc( ch ); } else { ch = 0; } } else { char* end = pptr(); if ( ch != EOF ) { *end ++ = ch; } if ( write( pbase(), end - pbase() ) == failed ) { ch = EOF; } else if ( ch == EOF ) { ch = 0; } setp( buffer, buffer + bufferSize - 1 ); } return ch; } int sync() { return (pptr() == pbase() || write( pbase(), pptr() - pbase() ) != failed) ? 0 : -1; } 的:

xsputn

一般情况下,我不会打扰streamsize xsputn(char const* p, streamsize n) { streamsize results = 0; if ( pptr() == pbase() || write( pbase(), pptr() - pbase() ) != failed ) { if ( write(p, n) != failed ) { results = n; } } setp( buffer, buffer + bufferSize - 1 ); return results; } ,但如果是您的客户 代码输出了很多长字符串,它可能很有用。 这样的事情可以解决问题:

{{1}}