首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止qDebug()写入std输出

防止qDebug()写入std输出
EN

Stack Overflow用户
提问于 2018-06-15 12:12:13
回答 1查看 743关注 0票数 1

我正在使用qDebug()qInfo()等结合qInstallMessageHandler来编写qInfo()。在执行应用程序时,我还会在批处理屏幕上获得一个输出。

我只找到了QT_NO_DEBUG_OUTPUT,但是我想在运行时切换这个配置。有没有办法阻止Qt写到std输出?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-15 18:25:54

遗憾的是,没有,您只能访问消息,但不能阻止写入std输出。

在Qt 5中,这至少是错误的。消息打印代码如下所示:您可以清楚地看到只使用消息处理程序:

代码语言:javascript
复制
if (grabMessageHandler()) {
    // prefer new message handler over the old one
    if (msgHandler.load() == qDefaultMsgHandler
            || messageHandler.load() != qDefaultMessageHandler) {
        (*messageHandler.load())(msgType, context, message);
    } else {
        (*msgHandler.load())(msgType, message.toLocal8Bit().constData());
    }
    ungrabMessageHandler();
} else {
    fprintf(stderr, "%s\n", message.toLocal8Bit().constData());
}

如您所见,只有在从fprintf(stderr, ...)本身中检测到递归时,messageHandler才是回退。

因此,要防止任何调试输出,只需实现并设置自己的messageHandler

要完全关闭Qt中的所有调试输出,请执行以下工作:

代码语言:javascript
复制
#include <QtCore>
int main() {
  qDebug() << "I'm not quiet at all yet";
  qInstallMessageHandler(+[](QtMsgType, const QMessageLogContext &, const QString &){});
  qDebug() << "I'm very, very quiet";
}

无论如何,应用程序范围内的文件记录器的合理实现可能如下所示:它不会不必要地重新创建QTextStream;它将使用QString::toUtf8(),并显式地写入行尾。

代码语言:javascript
复制
#include <QtCore>

class Logger {
   static struct Data {
      Logger *instance;
      QtMessageHandler chainedHandler;
   } d;
   bool m_isOpen;
   QFile m_logFile;
   QtMessageHandler m_oldHandler = {};
   static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
      if (d.instance)
         d.instance->log(msg);
      if (d.chainedHandler)
         d.chainedHandler(type, context, msg);
   }
public:
   enum ChainMode { DontChain, Chain };
   Logger() {
      Q_ASSERT(!instance());
      m_logFile.setFileName("myLog.txt");
      m_isOpen = m_logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
      d.instance = this;
   }
   ~Logger() { uninstallHandler(); }
   bool isOpen() const { return m_isOpen; }
   void installHandler(ChainMode mode) {
      Q_ASSERT(!m_oldHandler);
      m_oldHandler = qInstallMessageHandler(handler);
      if (mode == Chain)
         d.chainedHandler = m_oldHandler;
   }
   void uninstallHandler() {
      if (m_oldHandler) {
         m_oldHandler = nullptr;
         d.chainedHandler = nullptr;
         qInstallMessageHandler(m_oldHandler);
      }
   }
   /// This method is *not* thread-safe. Use with a thread-safe wrapper such as `qDebug`.
   void log(const QString & msg) {
      if (isOpen()) {
         m_logFile.write(msg.toUtf8());
         m_logFile.write("\n", 1);
      }
   }
   /// Closes the log file early - this is mostly used for testing.
   void endLog() {
      uninstallHandler();
      m_logFile.close();
   }
   static Logger *instance() { return d.instance; }
};

Logger::Data Logger::d;

template <typename T> QByteArray streamOutputFor(const T &data) {
   QBuffer buf;
   buf.open(QIODevice::ReadWrite | QIODevice::Text);
   QTextStream s(&buf);
   s << data << endl;
   buf.close();
   return buf.data();
}

QByteArray readEnd(const QString &fileName, int count) {
   QFile file(fileName);
   if (file.open(QIODevice::ReadOnly | QIODevice::Text) && file.size() >= count) {
      file.seek(file.size() - count);
      return file.readAll();
   }
   return {};
}

void test() {
   auto const entry = QDateTime::currentDateTime().toString().toUtf8();
   Q_ASSERT(Logger::instance()->isOpen());
   qDebug() << entry.data();
   Logger::instance()->endLog();

   auto reference = streamOutputFor(entry.data());
   auto readback = readEnd("myLog.txt", reference.size());
   Q_ASSERT(!reference.isEmpty());
   Q_ASSERT(readback == reference);
}

int main() {
   Logger logger;
   logger.installHandler(Logger::DontChain);
   qDebug() << "Something or else";
   test();
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50875371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档