Question

I'm trying to create a Logger class using QFile and QTextStream but I can't find an efficient way of doing it. I just want to create a log(...) function in it.

I know it works if I do the following:

void CLogger::log(QString strLog,int nType) {
    QFile file(m_strFileName);
    file.open( QIODevice::Append | QIODevice::Text );
    QTextStream logStream(&file);
    logStream << nType << "-" << strLog;
    file.close();
}

But It is quite nasty. I don't want to create a QFile object at every log line I insert.

So from that, I tried several different ways like:

1) (with QFile *m_pFile as member)

CLogger::CLogger()
{
    m_pFile = new QFile(m_strFileName);
}
void CLogger::log(QString strLog,int nType)
{
    m_pFile->open( QIODevice::Append | QIODevice::Text );
    QTextStream logStream(m_pFile);
    logStream << nType << "-" << strLog;
    m_pFile.close();
}

or

2) (with QFile *m_pFile and QTextStream *m_pLogStream as members)

CLogger::CLogger()
{
    m_pFile = new QFile(m_strFileName);
    m_pFile->open( QIODevice::Append | QIODevice::Text );
    m_pLogStream = new QTextStream(m_pFile);
}
void CLogger::log(QString strLog,int nType)
{
    *m_pLogStream << nType << "-" << strLog;
}

In the first case, I get:

C2248: 'QTextStream::QTextStream' : cannot access private member declared in class 'QTextStream'

in the 2nd, *m_pLogStream is not equivalent to a QTextStream&.

What am I doing wrong?

Was it helpful?

Solution

Actually it is not such a bad solution to open (and close) the log file every time you need to log something (unless you log 1000 times every second... but then noone would be able to process that amount of data ...). This not only allows you to have a very stable log (since you do not keep the file open all the time, so you are no depending on the flushing of the oeprating system), but also would allow you to be able to implement features as log rolling, and other niceties.

If you keep the log file open, in case of an unwanted "crash" you might not get all the log lines, depending of course how your OS is handling this ungraceful exits.

Here is a piece of code we use for logging:

QMutexLocker locker(&m_lineLoggerMutex);

QFile f(getLogFileName());
doRollLogsIfNeeded(static_cast<qint64>(f.size() + lineToBelogged.length()));

// Do not open in append mode but seek() to avoid warning for unseekable
// devices, note that if open is made with WriteOnly without Append, the
// file gets truncated
if (!f.open(QIODevice::ReadWrite | QIODevice::Text))
{
    QTextStream out(stdout);
    out << "CANNOT OPEN LOG FILE: " << getLogFileName();
    return;
}
// seek() does nothing on sequential devices, this is in essence what QFile
// does when Append flag is set in open() but without warning (on Qt 4.8.3)
// However, Qt 4.8.1 issues the warning, so check it explicitly
if (!f.isSequential())
{
    f.seek(f.size());
}

QTextStream out(&f);
out << lineToBelogged;

This goes in a method, and the destructors take care of the closing of the devices.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top