将 ostream 重定向到文件不起作用

发布于 2024-09-08 02:31:19 字数 2493 浏览 3 评论 0原文

我有一个自定义日志记录系统,它允许我根据当前选择的详细程度将信息发送到日志文件和控制台。现在,我遇到的问题是输出到文件,输出到控制台工作正常。

下面是一个示例:

     ilra_talk << "Local IP: " << systemIP() << " |  Hostname: " << systemhostname() << endl;
     // the systemIP() and systemhostname() functions have already been defined

这应该会导致系统的当前本地 IP 和主机名被打印到文件中。然而,它只会导致信息被打印到控制台,尽管该函数如何重载以导致它打印到两者。

我概述了下面的代码。感谢任何帮助(一如既往)。

当前存在 ilra_talk 的定义,这会导致创建新的类对象:

#define ilra_talk ilra(__FUNCTION__,0)

类定义如下:

class ilra
{
    static int ilralevel_set; // properly initialized in my main .cpp
    static int ilralevel_passed; // properly initialized in my main .cpp
    static bool relay_enabled; // properly initialized in my main .cpp
    static bool log_enabled; // properly initialized in my main .cpp
    static ofstream logfile; // properly initialized in my main .cpp
public:
    // constructor / destructor
    ilra(const std::string &funcName, int toset)
    {
        ilralevel_passed = toset;
    }
    ~ilra(){};

    // enable / disable irla functions
    static void ilra_verbose_level(int toset){
        ilralevel_set = toset;
    }
    static void ilra_log_enabled(bool toset){
        log_enabled = toset;

        if (log_enabled == true){
            // get current time
            time_t rawtime;
            time ( &rawtime );

            // name of log file (based on time of application start)
            stringstream logname_s;
            string logname = "rclient-";
            logname_s << rawtime;
            logname.append(logname_s.str());

            // open a log file
            logfile.open(logname.c_str());
        }
    }

    // output
    template <class T>
    ilra &operator<<(const T &v)
    {
        if(log_enabled == true){ // log_enabled is set to true
            logfile << v; 
            logfile << "Test" << endl;  // test will show up, but intended information will not appear
            }
        if(ilralevel_passed <= ilralevel_set)
            std::cout << v;
        return *this;
    }

    ilra &operator<<(std::ostream&(*f)(std::ostream&))
    {
        if(log_enabled == true) // log_enabled is set to true
            logfile << *f;
        if(ilralevel_passed <= ilralevel_set)
            std::cout << *f;
        return *this;
    }
};  // end of the class

I have a custom logging system which allows me to send information to a log file and the console depending on the verbosity currently selected. Right now, the trouble I am having is with the output to the file, with output to the console working fine.

Here is an example:

     ilra_talk << "Local IP: " << systemIP() << " |  Hostname: " << systemhostname() << endl;
     // the systemIP() and systemhostname() functions have already been defined

This should result in the current local IP and hostname of the system being printed to a file. However, it is only resulting in the information being printed to the console, despite how the function is overloaded to result in it printing to both.

I've outlined the code below. Any assistance is appreciated (as always).

A definition currently exists for ilra_talk which results in a new class object being created:

#define ilra_talk ilra(__FUNCTION__,0)

The class definition the following:

class ilra
{
    static int ilralevel_set; // properly initialized in my main .cpp
    static int ilralevel_passed; // properly initialized in my main .cpp
    static bool relay_enabled; // properly initialized in my main .cpp
    static bool log_enabled; // properly initialized in my main .cpp
    static ofstream logfile; // properly initialized in my main .cpp
public:
    // constructor / destructor
    ilra(const std::string &funcName, int toset)
    {
        ilralevel_passed = toset;
    }
    ~ilra(){};

    // enable / disable irla functions
    static void ilra_verbose_level(int toset){
        ilralevel_set = toset;
    }
    static void ilra_log_enabled(bool toset){
        log_enabled = toset;

        if (log_enabled == true){
            // get current time
            time_t rawtime;
            time ( &rawtime );

            // name of log file (based on time of application start)
            stringstream logname_s;
            string logname = "rclient-";
            logname_s << rawtime;
            logname.append(logname_s.str());

            // open a log file
            logfile.open(logname.c_str());
        }
    }

    // output
    template <class T>
    ilra &operator<<(const T &v)
    {
        if(log_enabled == true){ // log_enabled is set to true
            logfile << v; 
            logfile << "Test" << endl;  // test will show up, but intended information will not appear
            }
        if(ilralevel_passed <= ilralevel_set)
            std::cout << v;
        return *this;
    }

    ilra &operator<<(std::ostream&(*f)(std::ostream&))
    {
        if(log_enabled == true) // log_enabled is set to true
            logfile << *f;
        if(ilralevel_passed <= ilralevel_set)
            std::cout << *f;
        return *this;
    }
};  // end of the class

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寻找我们的幸福 2024-09-15 02:31:19

我认为代码没有完全错误,尽管我个人会进行两项更改:

  1. 将 logfile.flush() 放入 ilra::~ilra() 中。日志记录和缓冲不是朋友。

  2. static ofstream logfile 更改为 static ofstream *logfile:在 ilra_log_enabled() 中分配/删除它,并在 ilra_log_enabled() 中添加 NULL 检查。 <运营商。我更喜欢具有明确生命周期的对象。

总的来说,由于日志记录非常消耗性能,因此我从不使用 iostream,而是坚持使用类似 printf() 的宏:日志记录检查是在宏中进行的,无需函数调用。这有一个重要的副作用:如果不需要日志记录,则根本不会评估参数列表。在您的情况下,不可能避免调用函数,例如 systemIP()systemhostname(),因为对日志级别/等的检查是在它们已经完成之后完成的。已被调用。例如,使用宏,我还可以从发布版本中完全删除调试级日志记录(或推论:在调试版本中,我可以拥有尽可能多的日志记录)。

I see nothing totally wrong with the code, though I personally would have made two changes:

  1. Put the logfile.flush() into the ilra::~ilra(). Logging and buffering are no friends.

  2. Change static ofstream logfile to static ofstream *logfile: allocated/delete it in ilra_log_enabled() and add NULL check in the << operators. I prefer objects with explicit life cycle.

Overall, since logging is a performance hog, I never use the iostreams for it and stick with the printf()-like macros: logging check is made without a function call, right in the macro. That has important side-effect: if no logging is needed then the parameter list isn't evaluated at all. In your case it is impossible to avoid the functions being called, e.g. systemIP() and systemhostname(), since the check for log level/etc is done after they are already have been called. With the macros I can also for example remove completely debug-level logging from release builds (or corollary: in a debug build I can have as much logging as I want).

一笔一画续写前缘 2024-09-15 02:31:19

看起来“Test”很可能是从其他地方打印出来的,事实上 log_enabled 在您将数据插入流中时并未设置。您是否尝试过无条件地将数据插入到 logfile 流中,或者在每次调用 operator<< 时打印出 log_enabled

或者,cout 的类型为 ostreamlogfile 的类型为 ofstream。您的转发操纵器功能是否有可能没有为 ofstream 完成其工作?

It looks like "Test" is most likely being printed from somewhere else, and that in fact log_enabled isn't set at the point you're inserting data into the stream. Have you tried unconditionally inserting the data into the logfile stream, or printing out log_enabled every time operator<< is called?

Alternately, cout has type ostream and logfile has type ofstream. Is it possible that your function to forward manipulators isn't doing its job for ofstream?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文