Qt QString 中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK 乱码与转码问题
代碼如下:如果不不設(shè)全局的字符集是utf-8,那么網(wǎng)上一般的方法是可以轉(zhuǎn)的。如下程序中 #define DD 1的情況下;但是如果設(shè)置了全局的utf-8,再用以前的方法:
等網(wǎng)上類似的方法,都會出現(xiàn)轉(zhuǎn)代漢字不成功,但能轉(zhuǎn)代ASICC碼的情況。漢字都成了問號的ASICC碼63。這是因?yàn)闆]有用對方法沒有用轉(zhuǎn)換utf-8碼的方法。
轉(zhuǎn)碼是件很復(fù)雜的事。
| #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 //沒有設(shè)置全局的是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(); } |
以下是在網(wǎng)上找的,感覺很好,可以一塊理解:
這個好像就是用幾種不同的字符,但不會出錯,不像我們一種都搞不定
http://hi.baidu.com/codeworkman/blog/item/5c0d7516c5c03215c83d6dcc.html
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的子集,通常設(shè)成哪個都一樣的
????? 所謂的QString轉(zhuǎn)char*,結(jié)果并不相同,根據(jù)編碼格式不同而不同
????? QString轉(zhuǎn)unicode,不用轉(zhuǎn),QString本身就是unicode
????? QString的根本是QChar數(shù)組,但不是以0結(jié)尾,有大小,QChar的根本是ushot
????? Qt中unicode聲明:可以用wchar_t,也可以用ushot,沒有WCHAR
????? QByteArray可以理解為char類型的動態(tài)數(shù)組,有大小,不是以\0結(jié)尾
??? */
??? /*
??????? ui創(chuàng)建1個列表框QListWidget,和1個按鈕即可
??????? 用windows記事本分別創(chuàng)建4種文件,本例可直接打開
??????? ANSI:沒有文件頭,2字節(jié)/漢字,1字節(jié)/英文
??????? UTF-8:文件頭[0xEF,0xBB,0xBF],3字節(jié)/漢字,1字節(jié)/英文
??????? Unicode:文件頭[0xFF,0xFE],2字節(jié)/漢字,2字節(jié)/英文
??????? Unicode big endian :文件頭[0xFE,0xFF],同Unicode,字節(jié)序相反
??????? QString轉(zhuǎn)char*的規(guī)則同上;
??? */
??? /*
??? QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
??? QTextCodec::setCodecForTr(QTextCodec::codecForName("gb2312"));
??? QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
??? QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
??? 如下使用想要得到正確結(jié)果必須使用類似以上的語句
??? 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;
??? //轉(zhuǎn)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);
??? //?轉(zhuǎn)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);
??? //?轉(zhuǎn)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(" "));
}
以下這個我認(rèn)為是中文字符的深入理解吧:
http://hi.baidu.com/cyclone/blog/item/9d7293130e5a498d6538dbf1.html
QString 與中文問題 2010-07-11 17:04
| (更新:本文的姊妹篇?Qt中translate、tr關(guān)系 與中文問題?) 首先呢,聲明一下,QString 是不存在中文支持問題的,很多人遇到問題,并不是本身 QString 的問題,而是沒有將自己希望的字符串正確賦給QString。 很簡單的問題,"我是中文"這樣寫的時候,它是傳統(tǒng)的 char 類型的窄字符串,我們需要的只不過是通過某種方式告訴QString 這四個漢字采用的那種編碼。而問題一般都出在很多用戶對自己當(dāng)前的編碼沒太多概念, 于是 一個簡 單的 Qt 程序下面這個小程序,估計(jì)大家會感到比較親切。似乎有相當(dāng)多的中文用戶嘗試寫過這樣的代碼: #include <QtGui/QApplication>#include <QtGui/QLabel> int main(int argc, char **argv) { QApplication app(argc, argv); QString a= "我是漢字"; QLabel label(a); label.show(); return app.exec(); } 編碼,保存,編譯,運(yùn)行,一切都很順利,可是結(jié)果呢:
出乎意料,界面上中文沒顯示出來,出現(xiàn)了不認(rèn)識字符。?于是開始用搜索引擎搜索,開始上論壇發(fā)帖或抱怨 最后被告知,下面的語句之一可以解決問題: QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); 兩條指令挨個一試,確實(shí)可以解決(多數(shù)用戶是第一條,其他用戶是第二條)。那么,為什么會這樣呢? 兩種亂碼什么時候出現(xiàn)對這個問題,我想大家可能都有話說。在繼續(xù)之前,我們先列個表,看看兩種亂碼分別在那種情況下出現(xiàn): 我們只列舉大家最常用的3個編譯器(微軟VS的中的cl,Mingw中的g++,Linux下的g++),源代碼分別采用?GBK?和?不帶BOM的UTF-8??以及?帶BOM的UTF-8?這3中編碼進(jìn)行保存。
采用3種不同編碼保存的源代碼文件,分別用3種不同的編譯器編譯,形成9種組合,除掉一種不能工作的情況,兩種亂碼出現(xiàn)的情況各占一半。 從中我們也可以看出,亂碼和操作系統(tǒng)原本是沒有關(guān)系的。但我們在 Windows 一般用的GBK,linux一般用的是不帶BOM的UTF-8。如果我們只考慮帶*的情況,也可以說兩種亂碼和系統(tǒng)有關(guān)。 QString 為什么會亂碼呢真的是 QString 亂碼了嗎?我們可以問問自己,我們抱怨的對象是不是搞錯了? 繼續(xù)之前,先明確幾個概念: 明確概念0:
QString a= str; 或 char str[] = "我是漢字";QString a= str; 等 明確概念1:
這個是問題的根源,不妨做個試驗(yàn),將前面的源代碼保存成GBK編碼,用16進(jìn)制編輯器能看到引號內(nèi)是ce?d2?ca?c7?ba?ba?d7?d6這樣8個字節(jié)。 現(xiàn)在將該文件拷貝到正體(繁體)中文的Windows中,用記事本打開會什么樣子呢? ...QString a= "扂岆犖趼"; QLabel label(a); label.show(); ... 那么放到歐美人的Windows系統(tǒng)中,再用記事本打開呢? ...QString a= "?òê?oo×?"; QLabel label(a); label.show(); ... 同一個文件,未做任何修改,但其中的8個字節(jié)ce?d2?ca?c7?ba?ba?d7?d6,對用GBK的大陸人,用BIG5的港澳臺同胞,以及用Latin-1的歐洲人看來,看到的卻是完全不同的文字。 明確概念2:
GBK編碼下的 const char * str = "我是漢字"等價(jià)于 const char * str = "\xce\xd2\xca\xc7\xba\xba\xd7\xd6";當(dāng)用UTF-8編碼時,等價(jià)于 const char * str = "\xe6\x88\x91\xe6\x98\xaf\xe6\xb1\x89\xe5\xad\x97";注意:這個說法不全對,比如保存成帶BOM的UTF-8,用cl編譯器時,漢字本身是UTF-8編碼,但程序內(nèi)保存時卻是對應(yīng)的GBK編碼。 明確概念3:
QString內(nèi)部采用的是 Unicode,它可以同時存放GBK中的字符"我是漢字",BIG5中的字符"扂岆犖趼" 以及Latin-1中的字符"?òê?oo×?"。 一個問題是,源代碼中的這8個字節(jié)"\xce\xd2\xca\xc7\xba\xba\xd7\xd6",該怎么轉(zhuǎn)換成Unicode并存到 QString 內(nèi)?按照GBK、BIG5、Latin-1還是其他方式... 在你不告訴它的情況下,它默認(rèn)選擇了Latin-1,于是8個字符"?òê?oo×?"的unicode碼被存進(jìn)了QString中。最終,8個Latin字符出現(xiàn)在你期盼看到4中文字符的地方,所謂的亂碼出現(xiàn)了 QString 工作方式const char * str = "我是漢字";QString a= str; 其實(shí)很簡單的一個問題,當(dāng)你需要從窄字符串 char* 轉(zhuǎn)成Unicode的QString字符串的,你需要告訴QString你的這串char* 中究竟是什么編碼?GBK、BIG5、Latin-1 理想情況就是:將char* 傳給QString時,同時告訴QString自己的編碼是什么: 就像下面的函數(shù)一樣,QString的成員函數(shù)知道按照何種編碼來處理 C 字符串 QString QString::fromAscii ( const char * str, int size = -1 )QString QString::fromLatin1 ( const char * str, int size = -1 ) QString QString::fromLocal8Bit ( const char * str, int size = -1 ) QString QString::fromUtf8 ( const char * str, int size = -1 ) 單QString 只提供了這幾個成員函數(shù),遠(yuǎn)遠(yuǎn)滿足不了大家的需求,比如,在簡體中文Windows下,local8Bit是GBK,可是有一個char串是 BIG5 或 Latin-2怎么辦? 那就動用強(qiáng)大的QTextCodec吧,首先QTextCodec肯定知道自己所負(fù)責(zé)的編碼的,然后你把一個char串送給它,它就能正確將其轉(zhuǎn)成Unicode了。 QString QTextCodec::toUnicode ( const char * chars ) const可是這個調(diào)用太麻煩了,我就想直接 QString a= str;或 QString a(str);這樣用怎么辦? 這樣一來肯定沒辦法同時告訴 QString 你的str是何種編碼了,只能通過其他方式了。這也就是開頭提到的 QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); 設(shè)置QString默認(rèn)采用的編碼。而究竟采用哪一個,一般來說就是源代碼是GBK,就用GBK,源代碼是UTF-8就用UTF-8。但有一個例外,如果你保存成了帶BOM的UTF-8而且用的微軟的cl編譯器,此時仍是GBK。 |
最后是簡單的編程上的類型轉(zhuǎn)換,就是具體方法的應(yīng)用:
http://blog.csdn.net/ghostyu/article/details/6998640
qt學(xué)習(xí)筆記(三) QString char int之間的轉(zhuǎn)換
char *ch1="hello11";
const char *ch2="hello22";
ch2 = ch1;//不報(bào)錯,但有警告
ch1 = (char *)ch2;
char 轉(zhuǎn)換為 QString 其實(shí)方法有很多中,我用的是: char a='b';
QString str;
str=QString(a);
QString 轉(zhuǎn)換為 char
方法也用很多中
QString str="abc";
char *ch;
ch = str.toLatin1.data();
QByteArray 轉(zhuǎn)換為 char *
char *ch;//不要定義成ch[n];
QByteArray byte;
ch = byte.data();
char * 轉(zhuǎn)換為 QByteArray
char *ch;
QByteArray byte;
byte = QByteArray(ch);
QString 轉(zhuǎn)換為 QByteArray
QByteArray byte;
QString string;
byte = string.toAscii();
QByteArray 轉(zhuǎn)換為 QString
QByteArray byte;
QString string;
string = QString(byte);
這里再對這倆中類型的輸出總結(jié)一下:
qDebug()<<"print";
qDebug()<<tr("print");
qDebug()<<ch;(ch 為char類型)
qDebug()<<tr(ch);
qDebug()<<byteArray;(byteArray是QByteArray類型)
qDebug()<<tr(byteArray);
qDebug()<<str;(str 為Qstring類型)
但是qDebug()<<tr(str);是不可以的,要想用tr()函數(shù)輸出QString類型的字符則要如下:
qDebug()<<tr(str.toLatin1);
int 轉(zhuǎn) QString
int a=10;
QString b;
b=QString::number(a)
QString 轉(zhuǎn)int
QString a="120"
int b;
b=a.toInt()
char * 與 const char *的轉(zhuǎn)換
char *ch1="hello11";
const char *ch2="hello22";
ch2 = ch1;//不報(bào)錯,但有警告
ch1 = (char *)ch2;
char 轉(zhuǎn)換為 QString
其實(shí)方法有很多中,我用的是:
char a='b';
QString str;
str=QString(a);
QString 轉(zhuǎn)換為 char
方法也用很多中
QString str="abc";
char *ch;
ch = str.toLatin1.data();
QByteArray 轉(zhuǎn)換為 char *
char *ch;//不要定義成ch[n];
QByteArray byte;
ch = byte.data();
char * 轉(zhuǎn)換為 QByteArray
char *ch;
QByteArray byte;
byte = QByteArray(ch);
QString 轉(zhuǎn)換為 QByteArray
QByteArray byte;
QString string;
byte = string.toAscii();
QByteArray 轉(zhuǎn)換為 QString
QByteArray byte;
QString string;
string = QString(byte);
這里再對這倆中類型的輸出總結(jié)一下:
qDebug()<<"print";
qDebug()<<tr("print");
qDebug()<<ch;(ch 為char類型)
qDebug()<<tr(ch);
qDebug()<<byteArray;(byteArray是QByteArray類型)
qDebug()<<tr(byteArray);
qDebug()<<str;(str 為Qstring類型)
但是qDebug()<<tr(str);是不可以的,要想用tr()函數(shù)輸出QString類型的字符則要如下:
qDebug()<<tr(str.toLatin1);
int 轉(zhuǎn) QString
int a=10;
QString b;
b=QString::number(a)
QString 轉(zhuǎn)int
QString a="120"
int b;
b=a.toInt()
另一個
1 QString --> string
QString.toStdString();
2 string --> QString
QString::fromStdString(string)
3 QString --->int,double,char *
QString::toInt()
QString::toDouble()
QString.toStdString().c_str();
4 int double char* --->string
可以采用<sstream>里的stringstream
以int 為例,int a = 3;
stringstream ss;
string strInt;
ss<<a;
ss>>strInt;
開始時所 說的病例程序:
背景都是紅色的代碼作用是相同的,但打出的結(jié)果不一樣,后面一個出不了正確的信息,這就是為什么開始說的臨時變量不能長時間使用
| #include <QtGui/QApplication> #include "widget.h" #include<QTextCodec> #include<QFont> #include"database.h" #include<QtGui> #include<QPushButton> #include <QByteArray> int main(int argc, char *argv[]) { QApplication app(argc, argv); 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); //if(!createConnection()) // return 1 ; QString aaa= "燈開kl"; QString bbb="機(jī)頂盒的控制字"; QString ccc = "頻道加" ; #if 0 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(); char *cc = ccc.toUtf8().data(); char a1[100],a2[100],a3[100]; memset(a1, 0, sizeof(a1)); memset(a2, 0, sizeof(a2)); memset(a3, 0, sizeof(a3)); strncpy(a1, ad, strlen(ad)); strncpy(a2, bb, strlen(bb)); strncpy(a3, cc, strlen(cc)); printf("ad=%s,size=%d\n",ad,strlen(ad)); printf("df=%s,size=%d\n",bb,strlen(bb)); printf("cd=%s,size=%d\n",cc,strlen(cc)) ; printf("a1=%s,size=%d\n",a1,strlen(a1)); printf("a2=%s,size=%d\n",a2,strlen(a2)); printf("a3=%s,size=%d\n",a3,strlen(a3)); int len1 = strlen(ad) ; int len2 = strlen(bb) ; //qDebug() << ad << len1 << bb << len2 ; #endif QPushButton cccc("AWQ WQ wq 制熱"); cccc.show(); sqlite3 *db; char *zErrMsg ; sqlite3_stmt *stmt; int Codec_Id = 1; if((sqlite3_open("room.db",&db))!=0){ qDebug() << "sqlite3 open is false"; } else{ qDebug() << "sqlite3 open is OK"; } char sql3[100]; int room_Id = 1 ; int Device_Id = 1 ; int Device_Type = 11 ; int Control_Bty = 11 ; int Control_Status = 1 ; int ncols ,rc ; sprintf(sql3,"insert into Codec values(%d,%d,%d,%d,%d,%d,'%s','%s','%s');",Codec_Id,room_Id,Device_Id,Device_Type,Control_Bty,Control_Status,a1,a2,a3); printf("sql3=%s\nlen=%d\n",sql3,strlen(sql3)); sqlite3_exec(db,sql3,NULL,NULL,&zErrMsg); printf("zErrMsg = %s \n", zErrMsg); //檢查插入的數(shù)據(jù)有沒有問題 memset(sql3,0,sizeof(sql3)) ; sprintf(sql3,"select * from Codec ;") ; int nrow = 0, ncolumn = 0; char **azResult; //二維數(shù)組存放結(jié)果 sqlite3_get_table(db, sql3,&azResult , &nrow , &ncolumn , &zErrMsg ); int i = 0 ; //printf("size=%d\n",strlen(azResult)); printf( "row:%d column=%d \n" , nrow , ncolumn ); printf( "\nThe result of querying is : \n" ); for( i=0 ; i<( nrow + 1 ) * ncolumn ; i++ ) printf( "size=%d azResult[%d] = %s\n",strlen(azResult[i]), i , azResult[i] ); //釋放掉 azResult 的內(nèi)存空間 sqlite3_free_table( azResult ); sqlite3_prepare(db,sql3,strlen(sql3),&stmt,NULL); ncols = sqlite3_column_count(stmt); rc = sqlite3_step(stmt); char *name ; while(rc == SQLITE_ROW){ name = (char *)sqlite3_column_text(stmt,0); fprintf(stderr,"Row:Codec_id=%s,%d\n",name,strlen(name)); //L_id 表示是燈的設(shè)備表的id rc = sqlite3_step(stmt); } sqlite3_close(db); printf("ad=%s,size=%d\n",ad,strlen(ad)); printf("df=%s,size=%d\n",bb,strlen(bb)); printf("cd=%s,size=%d\n",cc,strlen(cc)) ; return app.exec(); } |
總結(jié)
以上是生活随笔為你收集整理的Qt QString 中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK 乱码与转码问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Eclipse-cdt 配合 gdbse
- 下一篇: linux c编程操作数据库(sqlit