qDebug() <<
디버그 출력을 위해 많은 문을 사용하고 있습니다 . 셸 스크립트에 의존하지 않고 디버그 출력을 파일로 리디렉션 할 수있는 크로스 플랫폼 방법이 있습니까? 나는 open () 및 dup2 () 가 Linux에서 작업을 수행하지만 Windows에서 MinGW로 컴파일하여 작동합니까?
그리고 그것을 수행하는 Qt 방법이 있습니까?
답변:
qInstallMsgHandler
함수를 사용하여 메시지 처리기를 설치 한 다음을 사용 QTextStream
하여 디버그 메시지를 파일 에 쓸 수 있습니다 . 다음은 샘플 예입니다.
#include <QtGlobal>
#include <stdio.h>
#include <stdlib.h>
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
}
int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageOutput); // Install the handler
QApplication app(argc, argv);
...
return app.exec();
}
의 문서에서 가져온 것입니다 qInstallMsgHandler
(댓글 만 추가했습니다).
위의 예에서 함수 myMessageOutput
는 stderr
다른 파일 스트림으로 바꾸거나 함수를 완전히 다시 작성하려는 것을 사용합니다!
당신이 작성하고이 기능을 설치하면 모든 qDebug
(물론 qWarning
, qCritical
등) 메시지는 핸들러에 파일 당신이있는 거 쓰기로 리디렉션 될 것이다.
qDebug
, qWarning
등 을 사용하는 것에 따라 다른 파일에 다른 메시지를 출력 할 수도 있습니다 qCritical
!
qInstallMsgHandler
더 이상 사용되지 않고 qInstallMessageHandler
(동일한 아이디어) 로 대체되었습니다 . 5.0의 qInstallMsgHandler
경우 qt-project.org/doc/qt-5.0/qtcore/…에 있으며 qInstallMessageHandler
거기에도 있습니다. 5.1의 경우 qInstallMsgHandler
완전히 제거되었습니다.
void myMessageOutput(QtMsgType type, const char *msg) { ... }
#include <QApplication>
#include <QtDebug>
#include <QFile>
#include <QTextStream>
void myMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & msg)
{
QString txt;
switch (type) {
case QtDebugMsg:
txt = QString("Debug: %1").arg(msg);
break;
case QtWarningMsg:
txt = QString("Warning: %1").arg(msg);
break;
case QtCriticalMsg:
txt = QString("Critical: %1").arg(msg);
break;
case QtFatalMsg:
txt = QString("Fatal: %1").arg(msg);
break;
}
QFile outFile("log");
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << txt << endl;
}
int main( int argc, char * argv[] )
{
QApplication app( argc, argv );
qInstallMessageHandler(myMessageHandler);
...
return app.exec();
}
qInstallMessageHandler
하는 대신 사용해야 qInstallMsgHandler
합니다.
다음은 기본 메시지 처리기를 연결하는 작업 예제입니다.
@Ross Rogers 감사합니다!
// -- main.cpp
// Get the default Qt message handler.
static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = qInstallMessageHandler(0);
void myCustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
// Handle the messages!
// Call the default handler.
(*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg);
}
int main(int argc, char *argv[])
{
qInstallMessageHandler(myCustomMessageHandler);
QApplication a(argc, argv);
qDebug() << "Wello Horld!";
return 0;
}
다음은 앱이 Qt Creator에서 실행 된 경우 콘솔에 로그하고 debug.log
파일이 컴파일되고 독립 실행 형 앱으로 실행될 때 파일 에 로깅하는 크로스 플랫폼 솔루션 입니다.
main.cpp :
#include <QApplication>
#include <QtGlobal>
#include <QtDebug>
#include <QTextStream>
#include <QTextCodec>
#include <QLocale>
#include <QTime>
#include <QFile>
const QString logFilePath = "debug.log";
bool logToFile = false;
void customMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QHash<QtMsgType, QString> msgLevelHash({{QtDebugMsg, "Debug"}, {QtInfoMsg, "Info"}, {QtWarningMsg, "Warning"}, {QtCriticalMsg, "Critical"}, {QtFatalMsg, "Fatal"}});
QByteArray localMsg = msg.toLocal8Bit();
QTime time = QTime::currentTime();
QString formattedTime = time.toString("hh:mm:ss.zzz");
QByteArray formattedTimeMsg = formattedTime.toLocal8Bit();
QString logLevelName = msgLevelHash[type];
QByteArray logLevelMsg = logLevelName.toLocal8Bit();
if (logToFile) {
QString txt = QString("%1 %2: %3 (%4)").arg(formattedTime, logLevelName, msg, context.file);
QFile outFile(logFilePath);
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << txt << endl;
outFile.close();
} else {
fprintf(stderr, "%s %s: %s (%s:%u, %s)\n", formattedTimeMsg.constData(), logLevelMsg.constData(), localMsg.constData(), context.file, context.line, context.function);
fflush(stderr);
}
if (type == QtFatalMsg)
abort();
}
int main(int argc, char *argv[])
{
QByteArray envVar = qgetenv("QTDIR"); // check if the app is ran in Qt Creator
if (envVar.isEmpty())
logToFile = true;
qInstallMessageHandler(customMessageOutput); // custom message handler for debugging
QApplication a(argc, argv);
// ...and the rest of 'main' follows
로그 형식화는 QString("%1 %2: %3 (%4)").arg...
(파일 용) 및 fprintf(stderr, "%s %s: %s (%s:%u, %s)\n"...
(콘솔 용)에서 처리합니다.
음, 디버그 출력을 stderr와 다른 것으로 리디렉션해야하는 순간은 로깅 도구에 대해 생각할 수있는 순간이라고 말하고 싶습니다. 필요한 경우 라이브러리 에서 사용하는 것이 좋습니다 QxtLogger
( "QxtLogger 클래스는 사용하기 쉽고 확장하기 쉬운 로깅 도구입니다." ) Qxt
.
다음은 stderr
및 파일에 모두 로깅하는 간단한 스레드 안전 관용적 Qt 예제입니다 .
void messageHandler (QtMsgType 유형, const QMessageLogContext & 컨텍스트, const QString & 메시지) { 정적 QMutex 뮤텍스; QMutexLocker 잠금 (& mutex); 정적 QFile logFile (LOGFILE_LOCATION); static bool logFileIsOpen = logFile.open (QIODevice :: Append | QIODevice :: Text); std :: cerr << qPrintable (qFormatLogMessage (유형, 컨텍스트, 메시지)) << std :: endl; if (logFileIsOpen) { logFile.write (qFormatLogMessage (유형, 컨텍스트, 메시지) .toUtf8 () + '\ n'); logFile.flush (); } }
qInstallMessageHandler(messageHandler)
다른 답변에 설명 된대로 설치하십시오 .