qInstallMessageHandler 问题

本文详细介绍了如何使用Qt的qInstallMessageHandler函数自定义应用程序的日志输出,包括文件名、行号和函数名等信息,并探讨了Qt中QString与不同字符编码之间的转换方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

qInstallMessageHandler 问题

fprintf是ANSI的,UNICODE的,要用fwprintf;也可以用_ftprintf来同时兼容ANSI和UNICODE;

The default message handler prints the message to the standard output under X11 or to the debugger under Windows. If it is a fatal message, the application aborts immediately.

Only one message handler can be defined, since this is usually done on an application-wide basis to control debug output.

To restore the message handler, call qInstallMessageHandler(0).

Example:

#include <qapplication.h>
  #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);
      QApplication app(argc, argv);
      ...
      return app.exec();
  }

This function was introduced in Qt 5.0.

qt Release 版本日志:文件名、函数名、行数—解决办法

qInstallMessageHandler来实现输出详细日志,输出文件名,行号,所在函数及事件,并写入文件。最后调用系统原来的函数,使信息像之前一样输出到调试窗口,便于开发。

QtMessageHandler gDefaultHandler = NULL;
 
//在其它地方调用qInstallMessageHandler设置新的输出函数,但保存原来的函数
gDefaultHandler = qInstallMessageHandler(myMessageOutput);
 
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QDateTime time = QDateTime::currentDateTime();
    QString strTime = time.toString("MM-dd hh:mm:ss");
    QString strMessage = QString("%1 File:%2  Line:%3  Function:%4\r\n  %5")
            .arg(strTime).arg(context.file).arg(context.line).arg(context.function).arg(msg);
 
    QString strMsg("");
    switch(type)
    {
    case QtDebugMsg:
        strMsg = QString("Debug");
        break;
    case QtInfoMsg:
        strMsg = QString("Info");
        break;
    case QtWarningMsg:
        strMsg = QString("Warning:");
        break;
    case QtCriticalMsg:
        strMsg = QString("Critical:");
        break;
    case QtFatalMsg:
        strMsg = QString("Fatal:");
        break;
    default:
        strMsg = QString("Err");
        break;
    }
 
    strMessage = strMsg+strMessage;
    // 加锁
    static QMutex mutex;
    mutex.lock();
 
 
    // 输出信息至文件中(读写、追加形式)
    QFile file("D:\\log.txt");
    file.open(QIODevice::ReadWrite | QIODevice::Append);
    QTextStream stream(&file);
    stream << strMessage << "\r\n";
    file.flush();
    file.close();
 
    // 解锁
    mutex.unlock();
 
    //用系统原来的函数完成原来的功能. 比如输出到调试窗
    if(gDefaultHandler)
    {
        gDefaultHandler(type,context,msg);
    }
 
}

上面代码里使用gDefaultHandler 保留了qInstallMessageHandler返回的系统原来的函数,最后再调用。这样qDebug()、qInfo()的信息和之前一样写入调试窗口,同时也写入了文件。

Release 版本默认不包含这些信息:文件名、函数名、行数,需要在项目文件加入以下代码,加入后最好重新构建项目使之生效:

DEFINES += QT_MESSAGELOGCONTEXT

Qt QString 中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK 乱码与转码问题

代码如下:如果不不设全局的字符集是utf-8,那么网上一般的方法是可以转的。如下程序中 #define DD 1的情况下;但是如果设置了全局的utf-8,再用以前的方法:
QByteArray ba=aaa.toLatin1();
const char *c_str = ba.data();
PS:c_str所指向的内存单元,如果你想长时间使用你应该复制出来,要不可能过数行代码后,你再读你的数据,c_str所指向的内存单元就不是你以前读的内容了。函数返回的指针临时变量,不能长时间使用!!!!!!!
具体代理在本贴最后补充出来:

等网上类似的方法,都会出现转代汉字不成功,但能转代ASICC码的情况。汉字都成了问号的ASICC码63。这是因为没有用对方法没有用转换utf-8码的方法。
转码是件很复杂的事。

#include <QtGui/QApplication>
#include<QTextCodec>
#include<QFont>
#include<QtGui>
#include <QByteArray>
#define DD 0
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    #if DD
            //没有设置全局的是utf-8字符
    #else
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
    QFont font;
    font.setFamily(("WenQuanYi Zen Hei"));
    font.setPointSize(12);
    app.setFont(font);
    app.setFont(font);
    #endif
    QString aaa= "你好a1234";
    QString bbb="哈哈afaf394的AAA";
    #if DD
    QByteArray ba=aaa.toLatin1();
    const char *c_str = ba.data();
    printf("c_str:%s:size=%d\n",c_str,strlen(c_str));
    char *p;
    p=(char *)c_str;
    printf("p=%d\n",*p);
    p++;
    printf("p=%d\n",*p);
    QString ddd(c_str);
    qDebug()<<ddd;
    #else
    char *ad = aaa.toUtf8().data();
    char *bb=   bbb.toUtf8().data();
     printf("ad=%s,size=%d\n",ad,strlen(ad));
     printf("df=%s,size=%d\n",bb,strlen(bb));
    #endif
    QPushButton ccc("AWQ WQ wq 你了");
    ccc.show();
    return app.exec();
}

以下是在网上找的,感觉很好,可以一块理解:

这个好像就是用几种不同的字符,但不会出错,不像我们一种都搞不定

Qt QString 中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK

#include <QFile>
#include <QFileDialog>
#include <QTextCodec>
#include <QByteArray>

void MainWindow::on_pushButton_clicked()
{    
    /*
      只有8位编码的才需要tr, unicode不要tr
      gb2312是GBK的子集,通常设成哪个都一样的
      所谓的QString转char*,结果并不相同,根据编码格式不同而不同
      QString转unicode,不用转,QString本身就是unicode
      QString的根本是QChar数组,但不是以0结尾,有大小,QChar的根本是ushot
      Qt中unicode声明:可以用wchar_t,也可以用ushot,没有WCHAR
      QByteArray可以理解为char类型的动态数组,有大小,不是以\0结尾
    */

    /*
        ui创建1个列表框QListWidget,和1个按钮即可

        用windows记事本分别创建4种文件,本例可直接打开
        ANSI:没有文件头,2字节/汉字,1字节/英文
        UTF-8:文件头[0xEF,0xBB,0xBF],3字节/汉字,1字节/英文
        Unicode:文件头[0xFF,0xFE],2字节/汉字,2字节/英文
        Unicode big endian :文件头[0xFE,0xFF],同Unicode,字节序相反

        QString转char*的规则同上;

    */

    /*
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
    QTextCodec::setCodecForTr(QTextCodec::codecForName("gb2312"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));

    如下使用想要得到正确结果必须使用类似以上的语句
    str = tr("显示中文");

    但以下这个可以直接使用
    strText = QString::fromLocal8Bit("显示中文");
    */

    ui->list->addItem(QString::fromLocal8Bit("--------显示中文----------"));

    QString strFileName = QFileDialog::getOpenFileName(this, tr("OpenFile"), ".", tr("Image Files(*.*)"));
    if(strFileName.length() == 0)
    {
        ui->list->addItem(tr("You didn't select any files."));
        return;
    }

    // 打开文件
    QFile *pFile = new QFile(strFileName);
    if (!pFile->open(QFile::ReadOnly))
    {
        ui->list->addItem(tr("open file fail %1: %2.").arg(strFileName).arg(pFile->errorString()));
        return;
    }
    ui->list->addItem(tr("open file ok %1").arg(strFileName));

    // 读文件
    qint64 fileSize = pFile->size();
    ui->list->addItem(tr("size = %1").arg(fileSize));
    char *pBuf = new char[fileSize];
    pFile->read(pBuf, fileSize);
    pFile->close();

    if(fileSize < 4)
    {
         ui->list->addItem(tr("fileSize < 4"));
         return;
    }

    QString strText;
    uchar *p = (uchar*)pBuf;


    if(p[0] == 0xEF && p[1] == 0xBB && p[2] == 0xBF)// UTF-8
    {
        ui->list->addItem(tr("UTF-8"));
        strText = QString::fromUtf8(pBuf + 3, fileSize - 3);
    }
    else if(p[0] == 0xFF && p[1] == 0xFE)// Unicode
    {
        ui->list->addItem(tr("Unicode"));
        strText = QString::fromWCharArray((wchar_t*)(pBuf + 2), (fileSize - 2) / 2);
    }
    else if(p[0] == 0xFE && p[1] == 0xFF)// Unicode big endian
    {
        ui->list->addItem(tr("Unicode big endian"));
        uchar uc = 0;
        for(int i = 3; i < fileSize; i += 2)
        {
            uc = p[i];
            p[i] = p[i - 1];
            p[i - 1] = uc;
        }
        strText = QString::fromWCharArray((wchar_t*)(pBuf + 2), (fileSize - 2) / 2);
    }
    else    //ANSI
    {       

        ui->list->addItem(tr("ANSI"));
        strText = QString::fromLocal8Bit(pBuf, fileSize);
    }

    ui->list->addItem(strText);

    QString strMsg, strTmp;

    //转unicode
    strMsg = tr("unicode: ");
    QChar *pData = strText.data();
    for(int i = 0; i < strText.size(); i++)
    {
        strTmp = tr("0x%1, ").arg(QString::number(pData[i].unicode(), 16).toUpper());
        strMsg += strTmp;
    }
    ui->list->addItem(strMsg);


    // 转gb2312
    strMsg = tr("gb2312:  ");
    QByteArray ary1 = strText.toLocal8Bit();
    uchar *puchar = (uchar*)ary1.data();
    for(int i = 0; i < ary1.size(); i++)
    {
        strTmp = tr("0x%1, ").arg(QString::number(puchar[i], 16).toUpper());
        strMsg += strTmp;
    }
    ui->list->addItem(strMsg);

    // 转uft8
    strMsg = tr("utf-8:   ");
    ary1 = strText.toUtf8();
    puchar = (uchar*)ary1.data();
    for(int i = 0; i < ary1.size(); i++)
    {
        strTmp = tr("0x%1, ").arg(QString::number(puchar[i], 16).toUpper());
        strMsg += strTmp;
    }
    ui->list->addItem(strMsg);

    ui->list->addItem(tr(" "));
}

以下这个我认为是中文字符的深入理解吧:

QString 与中文问题

(更新:本文的姊妹篇 Qt中translate、tr关系 与中文问题 )

首先呢,声明一下,QString 是不存在中文支持问题的,很多人遇到问题,并不是本身 QString 的问题,而是没有将自己希望的字符串正确赋给QString。

很简单的问题, “我是中文” 这样写的时候,它是传统的 char 类型的窄字符串,我们需要的只不过是通过某种方式告诉QString 这四个汉字采用的那种编码。而问题一般都出在很多用户对自己当前的编码没太多概念,

QString 与中文问题

https://www.cnblogs.com/bingcaihuang/archive/2011/03/17/1986895.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值