【问题标题】:Trying to derive from wfilebuf (filebuf) for logging尝试从 wfilebuf (filebuf) 派生以进行日志记录
【发布时间】:2011-05-09 11:15:46
【问题描述】:

我基本上是在尝试从 wfilebuf 派生,因此我既可以输出到文件,也可以截取输出以将其打印到控制台/调试窗口,如下所示: http://savingyoutime.wordpress.com/2009/04/21/ 和/或这里:http://savingyoutime.wordpress.com/2009/04/22/40/

(这里是古老的支持思想:http://www.horstmann.com/cpp/streams.txt

我几乎搞定了,但我似乎无法同时写入基础文件并查看输入。

我覆盖了类似于第二个示例的 sync() 函数,但似乎 pbase() 和 pptr() 始终为 NULL,除非我使用 setp(...) 设置缓冲区,但这似乎破坏了文件输出.该文件始终为空!

我对此的粗略尝试如下:

class LoggerBuffer : public wfilebuf {
// Functions
    public:
        LoggerBuffer();
        ~LoggerBuffer();
        void open(const wchar_t loggerFile[]);
        void close();
        int sync();
        int_type overflow(int_type c = EOF);
        void setState(int newState);
// Variables
    private:
        int currentState;
        static const int BUFFER_SIZE = 10;
        wchar_t buffer[BUFFER_SIZE];  
};

class LoggerStream : public wostream {
// Functions
    public:
         LoggerStream();
         ~LoggerStream();
         void open(const wchar_t loggerFile[] = 0);
         void close();
         void setState(int newState);
};

LoggerBuffer::LoggerBuffer() {
    wfilebuf::open("NUL", wios::out); currentState = 1;
}
LoggerBuffer::~LoggerBuffer() {
    wcout << "Destruction of LoggerBuffer" << endl;
}
void LoggerBuffer::open(const wchar_t loggerFile[]) {
    wcout << "LoggerBuffer Opening " << loggerFile << endl;
    close();
    wfilebuf* temp = wfilebuf::open(loggerFile, wios::out); //ios::out | ios::app | ios::trunc
    setp (buffer, buffer+(BUFFER_SIZE-1));
}
void LoggerBuffer::close() {
    wfilebuf::close();
}

int LoggerBuffer::sync() {
    wcout << "  Syncing ";
    int out_waiting = pptr() - pbase();
    wcout << out_waiting << " characters!";
    wcout << endl;
    wcout << "pptr(): " << (unsigned int)pptr() << endl;
    return wfilebuf::sync();
}
LoggerBuffer::int_type LoggerBuffer::overflow(int_type c) {
    wcout << "overflow! (" << (wchar_t)c << ")" << endl;
    if (c == EOF)
        return EOF;
    if (sync() == EOF)
        return EOF;
    return wfilebuf::overflow(c);
}
void LoggerBuffer::setState(int newState) {
    wcout << "New buffer state = " << newState << endl;
    currentState = newState;
}

LoggerStream::LoggerStream() : wostream(new LoggerBuffer), wios(0) {
}
LoggerStream::~LoggerStream() {
    delete rdbuf();
}
void LoggerStream::open(const wchar_t loggerFile[]) {
    wcout << "LoggerStream Opening " << loggerFile << endl;
    ((LoggerBuffer*)rdbuf())->open(loggerFile);
}
void LoggerStream::close() {
    ((LoggerBuffer*)rdbuf())->close();
}
void LoggerStream::setState(int newState) {
    wcout << "New stream state = " << newState << endl;
    ((LoggerBuffer*)rdbuf())->setState(newState);
}

完全披露:我之前问过一个类似的问题:Simple wostream logging class (with custom stream manipulators)

我想我已经解决了这个问题。

非常感谢任何帮助!谢谢!

【问题讨论】:

  • 我相信组合会比这里继承的类更可重用。还是找不到错误:(
  • 您是否为缓冲区语言环境和标准流语言环境设置了适当的编解码器?你试过输出 ASCII 字符串吗?

标签: c++ debugging logging ostream filebuf


【解决方案1】:

我会使用filtering streambuf,它本身不进行缓冲,而是将数据传递给每个目的地的真正的streambuf(即进行真正缓冲的)。这应该会大大简化你的代码,让你专注于你真正关心的部分。

【讨论】:

  • 虽然非缓冲流缓冲区确实更容易实现,但它们可能存在性能问题。
  • @Basilevs:如果您(例如)在没有缓冲的情况下写入实际文件,那会导致问题——但在这种情况下,您只是在写入另一个缓冲区。使用可以内联函数调用的体面的编译器,更多的缓冲(通常)不会有任何好处。
  • 虚拟呼叫没有内联。另请注意,您假设链接的实现在流的每个字节上调用溢出函数。这就是我的意思的开销——如果你想在大数据流上获得良好的性能,你应该尽量减少函数调用的数量。出于这个原因,最好覆盖 xsputn。
  • @Basilevs:如果编译器可以静态确定目标的类型,则可以内联虚拟调用。与往常一样,我会先让它工作,然后担心如果你发现它是一个瓶颈,让它更快。
  • 从 streambuf 派生然后仅在静态确定的上下文中使用它有什么意义? STL 缓冲区都是关于可互换性的。你是对的优化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-25
  • 1970-01-01
  • 1970-01-01
  • 2016-04-24
  • 2017-10-03
  • 2022-12-21
  • 2012-03-10
相关资源
最近更新 更多