一个自定义的ostream

Uri*_*Uri 21 c++

我需要一些指导或指导,了解如何实现自定义ostream.我的要求是:

  1. 一个带有'<<'运算符的类,用于多种数据类型.
  2. 目的是将输出发送到数据库.每条"线"都应该单独记录.
  3. 每个记录最重要的字段是文本(或blob),但其他一些字段,如时间等,大部分都可以自动推断出来
  4. 缓冲很重要,因为我不想为每条记录访问数据库.

首先,它是否值得从ostream中获得?从ostream得到什么?如果我的类只实现了很少的operator<<方法(包括一些自定义数据类型),该怎么办 我从ostream获得哪些功能?

假设我想要的是一个源自ostream的类,我需要一些指导来理解ostream和streambuf类之间的关系.我需要实施哪一个?看一些样本,似乎我根本不需要从ostream派生,只需给ostream构造函数一个自定义的streambuf.真的吗?这是规范的方法吗?

我需要在自定义streambuf中实现哪些虚拟功能?我已经看到了一些示例(包括这个站点:这里这里,还有更多),一些覆盖了该sync方法,而另一些覆盖了该overflow方法.我应该覆盖哪一个?另外,查看stringbuf和filebuf源(Visual Studio或GCC),这两个缓冲类都实现了streambuf的许多方法.

如果需要从streambuf派生的自定义类,是否可以从stringbuf(或任何其他类)而不是直接从streambuf获得任何好处?

至于"线".至少当我使用'endl'操纵器的类的用户是一个新行(即数据库中的记录)时,我想.也许 - 取决于努力 - 每个'\n'字符也应被视为新记录.谁为我的自定义ostream和/或streambuf获得通知?

Uri*_*Uri 24

ostream的自定义目标意味着实现您自己的ostreambuf.如果您希望streambuf实际缓冲(即不在每个字符后连接到数据库),最简单的方法是创建一个继承自的类std::stringbuf.您需要覆盖的唯一函数是sync()方法,只要刷新流就会调用该方法.

class MyBuf : public std::stringbuf
{
public:
    virtual int sync() {
        // add this->str() to database here
        // (optionally clear buffer afterwards)
    }
};
Run Code Online (Sandbox Code Playgroud)

然后,您可以std::ostream使用缓冲区创建:

MyBuf buff;
std::ostream stream(&buf)
Run Code Online (Sandbox Code Playgroud)

大多数人建议不要将流重定向到数据库,但是他们忽略了我的描述,即数据库基本上只有一个blob字段,所有文本都将在其中.在极少数情况下,我可能会将数据发送到其他字段.这可以通过我的流理解的自定义属性来促进.例如:

MyStream << "Some text " << process_id(1234) << "more text" << std::flush
Run Code Online (Sandbox Code Playgroud)

上面的代码将在数据库中创建一条记录:

blob: 'Some text more text'
process_id: 1234
Run Code Online (Sandbox Code Playgroud)

process_id()是一种返回结构的方法ProcessID.然后,在我的ostream的实现中,我有一个operator<<(ProcessID const& pid),它存储进程ID直到它被写入.效果很好!


zau*_*ufi 19

最简单的方法是继承std::streambuf和覆盖两个方法:

  • std::streamsize xsputn(const char_type* s, std::streamsize n)- 附加一个给定缓冲区,其大小提供给内部缓冲区,std::string例如;
  • int_type overflow(int_type c)- 将单个附加char到内部缓冲区.

您的streambuf可以根据您的需要构建(例如DB连接).在将内容添加到内部缓冲区后,您可以尝试将其拆分为行并将某些内容推入DB(或者只是缓冲SQL语句以便稍后执行).

要使用它:只需将您streambuf的任何std::ostream使用构造函数附加到它.

简单!我已经做了类似这样的事情来输出字符串到syslog - 一切都适用operator<<于用户定义的类的任何自定义.

  • 不会实现xsputn击败streambuf的所有目的?filebuf和stringbuf都不会覆盖此方法,而只会溢出(由stringbuf调用). (3认同)