定制的鸵鸟

A custom ostream

本文关键字:      更新时间:2023-10-16

我需要一些指导或指针来理解如何实现自定义ostream。我的要求是:

  1. 具有'<lt;'运算符
  2. 目的是将输出发送到数据库。每个"行"都应该指向一个单独的记录
  3. 每个记录最重要的字段都是文本(或blob),但其他一些字段(如时间等)大多可以自动推导出来
  4. 缓冲很重要,因为我不想对每个记录都使用数据库

首先,它值得从ostream派生吗?从ostream派生得到什么?如果我的类只实现了几个operator<<方法(包括一些自定义数据类型)会怎样。我可以从ostream获得哪些功能?

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

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

如果需要从streambuf派生的自定义类,那么从stringbuf(或任何其他类)而不是直接从streambuf派生会有什么好处吗?

至于"线条"。我希望至少当我的类的用户使用"endl"操纵器时是新行(即数据库中的记录)。也许——取决于努力——每个"\n"字符也应该被视为一个新记录。我的自定义ostream和/或streambuf会分别通知谁?

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)
}
};

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

MyBuf buff;
std::ostream stream(&buf)

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

MyStream << "Some text " << process_id(1234) << "more text" << std::flush

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

blob: 'Some text more text'
process_id: 1234

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

最简单的方法是继承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<<都可以正常工作。

my2c-我认为你处理这个问题的方式不对。流听起来可能是个好主意,但你也需要一种方法来指示行的末尾(如果有人忘记了怎么办?),然后是一个"批处理"方法,它明确地表明您确实在批处理该行,然后执行以将批处理推入。

任何基于流的操作都将依赖于类型(通常)来指示要填充哪一列,但如果有两个int呢?IMO,作为一个用户,它感觉不像是一种将记录插入数据库的自然方式。。。

要将字符输入/输出的新源或目标添加到iostreams机制,您应该创建一个新的streambuf类。流缓冲区类的任务是与存储字符的"外部设备"通信,并提供缓冲设施。

使用iostreams与数据库通信的问题是,数据库表与字符序列的概念不匹配。有点像在方洞里推一个圆钉子。streambuf只对字符进行操作。这是唯一提供给它的东西。这意味着streambuf必须解析提供给它它的字符流,以找到字段和记录分隔符。如果你决定走这条路,我预测你最终会在streambuf中编写一个CSV到SQL的转换器,只是为了让它正常工作。

您可能更适合在类中添加一些operator<<重载。你可以在这里查看Qt框架的想法。他们还可以使用operator<<向集合等添加项目。

相关文章:
  • 没有找到相关文章