2011-02-10 21 views
57

मैं डीबग आउटपुट के लिए qDebug() << कथन का उपयोग कर रहा हूं। क्या कोई क्रॉस-प्लेटफार्म तरीका है जिसे मैं शेल स्क्रिप्ट का उपयोग किए बिना फ़ाइल में उस डीबग आउटपुट को रीडायरेक्ट कर सकता हूं? मुझे लगता है कि open() और dup2() लिनक्स में काम करेगा, लेकिन क्या यह विंडोज़ में मिनीजीडब्ल्यू के साथ संकलित होगा?qDebug, qWarning, qCritical आदि आउटपुट को पुनर्निर्देशित करने के लिए कैसे?

और शायद ऐसा करने के लिए एक क्यूटी तरीका है?

उत्तर

85

आप 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 आदि) संदेशों को उस फ़ाइल पर रीडायरेक्ट किया जाएगा जिसे आप हैंडलर में लिख रहे हैं।

+3

अरे, बहुत बहुत धन्यवाद। न केवल मुझे डीबग आउटपुट को फ़ाइल में रीडायरेक्ट करने देगा, यह मुझे टाइमस्टैम्प की तरह अधिक उपयोगी जानकारी प्रिंट करने में सक्षम बनाता है :) – Septagram

+2

@ सप्तग्राम: बिल्कुल। आप हनल्डर में कुछ उपयोगी संदेश जोड़ सकते हैं; और आप 'qDebug',' qWarning', 'qCritical' और इसी तरह के उपयोग के आधार पर विभिन्न फ़ाइलों को अलग-अलग संदेशों को आउटपुट भी कर सकते हैं! – Nawaz

+1

वैसे, कॉलबैक जो वास्तविक आउटपुट करता है - शून्य myMessageOutput (QtMsgType प्रकार, const char * msg) - क्या एन्कोडिंग में यह संदेश प्राप्त होता है? – Septagram

5

ठीक है, मैं कहूंगा कि जिस क्षण आपको अपने डीबग आउटपुट को स्टीडर से अलग कुछ भी रीडायरेक्ट करने की आवश्यकता है, जब आप कुछ लॉगिंग टूल के बारे में सोच सकते हैं। यदि आपको लगता है कि आपको एक की आवश्यकता है तो मैं QxtLogger ("का उपयोग करने की अनुशंसा करता हूं। QxtLogger क्लास का उपयोग करना आसान है, लॉगिंग टूल का विस्तार करना आसान है।) Qxt लाइब्रेरी से।

11

here से सभी क्रेडिट spirit पर जाते हैं।

#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(); 
} 
+0

केस QtFatalMsg: ... abort(); // यह लॉग लिखने से पहले छोड़ देगा – raidsan

+0

@raidsan अच्छी तरह पकड़ा गया! –

+0

क्यूटी 5 से शुरू करें, 'qInstallMessageHandler' का उपयोग' qInstallMsgHandler' के बजाय संदेश हैंडलर को बदलने के लिए किया जाना चाहिए । – SuB

5

यहां डिफ़ॉल्ट संदेश हैंडलर को हुक करने का एक कामकाजी उदाहरण है।

धन्यवाद @ रॉस रोजर्स!

// -- 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; 
} 
2

यहाँ कंसोल के लिए लॉग इन करने के पार मंच समाधान है, अगर एप्लिकेशन क्यूटी निर्माता से और 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 

लॉग स्वरूपण और fprintf(stderr, "%s %s: %s (%s:%u, %s)\n"... (कंसोल के लिए) (फ़ाइल के लिए) QString("%1 %2: %3 (%4)").arg... द्वारा नियंत्रित किया जाता।

प्रेरणा: https://gist.github.com/polovik/10714049

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^