定制的鸵鸟
A custom ostream
我需要一些指导或指针来理解如何实现自定义ostream。我的要求是:
- 具有'<lt;'运算符
- 目的是将输出发送到数据库。每个"行"都应该指向一个单独的记录
- 每个记录最重要的字段都是文本(或blob),但其他一些字段(如时间等)大多可以自动推导出来
- 缓冲很重要,因为我不想对每个记录都使用数据库
首先,它值得从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<<
向集合等添加项目。
- 没有找到相关文章