2012-03-22 14:00
175人閱讀
評論(0)
代碼如下:如果不不設全局的字符集是utf-8,那么網上一般的方法是可以轉的。如下程序中 #define DD 1的情況下;但是如果設置了全局的utf-8,再用以前的方法:
QByteArrayba=aaa.toLatin1();
constchar*c_str=ba.data();
PS:c_str所指向的內存單元,如果你想長時間使用你應該復制出來,要不可能過數行代碼后,你再讀你的數據,c_str所指向的內存單元就不是你以前讀的內容了。函數返回的指針臨時變量,不能長時間使用!!!!!!!
具體代理在本貼最后補充出來:
等網上類似的方法,都會出現轉代漢字不成功,但能轉代ASICC碼的情況。漢字都成了問號的ASICC碼63。這是因為沒有用對方法沒有用轉換utf-8碼的方法。
轉碼是件很復雜的事。
#include
#include
#include
#include
#include
#defineDD0
intmain(intargc,char*argv[])
{
QApplicationapp(argc,argv);
#ifDD
//沒有設置全局的是utf-8字符
#else
QTextCodec*codec=QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
QFontfont;
font.setFamily(("WenQuanYiZenHei"));
font.setPointSize(12);
app.setFont(font);
app.setFont(font);
#endif
QStringaaa="你好a1234";
QStringbbb="哈哈afaf394的AAA";
#ifDD
QByteArrayba=aaa.toLatin1();
constchar*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);
QStringddd(c_str);
qDebug()<
#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
QPushButtonccc("AWQWQwq你了");
ccc.show();
returnapp.exec();
}
以下是在網上找的,感覺很好,可以一塊理解:
這個好像就是用幾種不同的字符,但不會出錯,不像我們一種都搞不定
Qt QString 中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK
#include
#include
#include
#include
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 與中文問題
2010-07-11 17:04
(更新:本文的姊妹篇Qt中translate、tr關系
與中文問題?)
首先呢,聲明一下,QString 是不存在中文支持問題的,很多人遇到問題,并不是本身 QString 的問題,而是沒有將自己希望的字符串正確賦給QString。
很簡單的問題,"我是中文"這樣寫的時候,它是傳統的 char 類型的窄字符串,我們需要的只不過是通過某種方式告訴QString 這四個漢字采用的那種編碼。而問題一般都出在很多用戶對自己當前的編碼沒太多概念,
于是
一個簡 單的 Qt 程序
下面這個小程序,估計大家會感到比較親切。似乎有相當多的中文用戶嘗試寫過這樣的代碼:
#include #include int main(int argc, char **argv){QApplication app(argc, argv);QString a= "我是漢字";QLabel label(a);label.show();return app.exec();}
編碼,保存,編譯,運行,一切都很順利,可是結果呢:
多數用戶看到
其他用戶看到
òê?oo×?
‘??ˉ?±‰? —
出乎意料,界面上中文沒顯示出來,出現了不認識字符。?于是開始用搜索引擎搜索,開始上論壇發帖或抱怨
最后被告知,下面的語句之一可以解決問題:
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
兩條指令挨個一試,確實可以解決(多數用戶是第一條,其他用戶是第二條)。那么,為什么會這樣呢?
兩種亂碼什么時候出現
對這個問題,我想大家可能都有話說。在繼續之前,我們先列個表,看看兩種亂碼分別在那種情況下出現:
我們只列舉大家最常用的3個編譯器(微軟VS的中的cl,Mingw中的g++,Linux下的g++),源代碼分別采用?GBK?和?不帶BOM的UTF-8?以及?帶BOM的UTF-8這3中編碼進行保存。
源代碼的編碼
編譯器
結果
GBK
cl
1
*
mingw-g++
1
*
g++
1
UTF-8(不帶BOM)
cl
2
mingw-g++
2
g++
2
*
UTF-8(帶BOM)
cl
1
mingw-g++
2
g++
編譯失敗
采用3種不同編碼保存的源代碼文件,分別用3種不同的編譯器編譯,形成9種組合,除掉一種不能工作的情況,兩種亂碼出現的情況各占一半。
從中我們也可以看出,亂碼和操作系統原本是沒有關系的。但我們在 Windows 一般用的GBK,linux一般用的是不帶BOM的UTF-8。如果我們只考慮帶*的情況,也可以說兩種亂碼和系統有關。
QString 為什么會亂碼呢
真的是 QString 亂碼了嗎?我們可以問問自己,我們抱怨的對象是不是搞錯了?
繼續之前,先明確幾個概念:
明確概念0:
"我是漢字" 是C語言中的字符串,它是char型的窄字符串。上面的例子可寫為
const char * str = "我是漢字";QString a= str;
或
char str[] = "我是漢字";QString a= str;
等
明確概念1:
源文件是有編碼的,但是這種純文本文件卻不會記錄自己采用的編碼
這個是問題的根源,不妨做個試驗,將前面的源代碼保存成GBK編碼,用16進制編輯器能看到引號內是ce?d2?ca?c7?ba?ba?d7?d6這樣8個字節。
現在將該文件拷貝到正體(繁體)中文的Windows中,用記事本打開會什么樣子呢?
...QString a= "扂岆犖趼";QLabel label(a);label.show();...
那么放到歐美人的Windows系統中,再用記事本打開呢?
...QString a= "òê?oo×?";QLabel label(a);label.show();...
同一個文件,未做任何修改,但其中的8個字節ce?d2?ca?c7?ba?ba?d7?d6,對用GBK的大陸人,用BIG5的港澳臺同胞,以及用Latin-1的歐洲人看來,看到的卻是完全不同的文字。
明確概念2:
如同我們都了解的'A'與'\x41'等價一樣。
GBK編碼下的
const char * str = "我是漢字"
等價于
const char * str = "\xce\xd2\xca\xc7\xba\xba\xd7\xd6";
當用UTF-8編碼時,等價于
const char * str = "\xe6\x88\x91\xe6\x98\xaf\xe6\xb1\x89\xe5\xad\x97";
注意:這個說法不全對,比如保存成帶BOM的UTF-8,用cl編譯器時,漢字本身是UTF-8編碼,但程序內保存時卻是對應的GBK編碼。
明確概念3:
QString 內部采用的是Unicode。
QString內部采用的是 Unicode,它可以同時存放GBK中的字符"我是漢字",BIG5中的字符"扂岆犖趼" 以及Latin-1中的字符"?òê?oo×?"。
一個問題是,源代碼中的這8個字節"\xce\xd2\xca\xc7\xba\xba\xd7\xd6",該怎么轉換成Unicode并存到 QString 內?按照GBK、BIG5、Latin-1還是其他方式...
在你不告訴它的情況下,它默認選擇了Latin-1,于是8個字符"?òê?oo×?"的unicode碼被存進了QString中。最終,8個Latin字符出現在你期盼看到4中文字符的地方,所謂的亂碼出現了
QString 工作方式
const char * str = "我是漢字";QString a= str;
其實很簡單的一個問題,當你需要從窄字符串 char* 轉成Unicode的QString字符串的,你需要告訴QString你的這串char* 中究竟是什么編碼?GBK、BIG5、Latin-1
理想情況就是:將char* 傳給QString時,同時告訴QString自己的編碼是什么:
就像下面的函數一樣,QString的成員函數知道按照何種編碼來處理 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 只提供了這幾個成員函數,遠遠滿足不了大家的需求,比如,在簡體中文Windows下,local8Bit是GBK,可是有一個char串是 BIG5 或 Latin-2怎么辦?
那就動用強大的QTextCodec吧,首先QTextCodec肯定知道自己所負責的編碼的,然后你把一個char串送給它,它就能正確將其轉成Unicode了。
QString QTextCodec::toUnicode ( const char * chars ) const
可是這個調用太麻煩了,我就想直接
QString a= str;
或
QString a(str);
這樣用怎么辦?
這樣一來肯定沒辦法同時告訴 QString 你的str是何種編碼了,只能通過其他方式了。這也就是開頭提到的
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
設置QString默認采用的編碼。而究竟采用哪一個,一般來說就是源代碼是GBK,就用GBK,源代碼是UTF-8就用UTF-8。但有一個例外,如果你保存成了帶BOM的UTF-8而且用的微軟的cl編譯器,此時仍是GBK。
最后是簡單的編程上的類型轉換,就是具體方法的應用:
char * 與 const char *的轉換
char *ch1="hello11";
const char *ch2="hello22";
ch2 = ch1;//不報錯,但有警告
ch1 = (char *)ch2;
char 轉換為 QString
其實方法有很多中,我用的是:
char a='b';
QString str;
str=QString(a);
QString 轉換為 char
方法也用很多中
QString str="abc";
char *ch;
ch = str.toLatin1.data();
QByteArray 轉換為 char *
char *ch;//不要定義成ch[n];
QByteArray byte;
ch = byte.data();
char * 轉換為 QByteArray
char *ch;
QByteArray byte;
byte = QByteArray(ch);
QString 轉換為 QByteArray
QByteArray byte;
QString string;
byte = string.toAscii();
QByteArray 轉換為 QString
QByteArray byte;
QString string;
string = QString(byte);
這里再對這倆中類型的輸出總結一下:
qDebug()<
qDebug()<
qDebug()<
qDebug()<
qDebug()<
qDebug()<
qDebug()<
但是qDebug()<
qDebug()<
int 轉 QString
int a=10;
QString b;
b=QString::number(a)
QString 轉int
QString a="120"
int b;
b=a.toInt()
char * 與 const char *的轉換
char *ch1="hello11";
const char *ch2="hello22";
ch2 = ch1;//不報錯,但有警告
ch1 = (char *)ch2;
char 轉換為 QString
其實方法有很多中,我用的是:
char a='b';
QString str;
str=QString(a);
QString 轉換為 char
方法也用很多中
QString str="abc";
char *ch;
ch = str.toLatin1.data();
QByteArray 轉換為 char *
char *ch;//不要定義成ch[n];
QByteArray byte;
ch = byte.data();
char * 轉換為 QByteArray
char *ch;
QByteArray byte;
byte = QByteArray(ch);
QString 轉換為 QByteArray
QByteArray byte;
QString string;
byte = string.toAscii();
QByteArray 轉換為 QString
QByteArray byte;
QString string;
string = QString(byte);
這里再對這倆中類型的輸出總結一下:
qDebug()<
qDebug()<
qDebug()<
qDebug()<
qDebug()<
qDebug()<
qDebug()<
但是qDebug()<
qDebug()<
int 轉 QString
int a=10;
QString b;
b=QString::number(a)
QString 轉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
可以采用里的stringstream
以int 為例,int a = 3;
stringstream ss;
string strInt;
ss<
ss>>strInt;
開始時所 說的病例程序:
背景都是紅色的代碼作用是相同的,但打出的結果不一樣,后面一個出不了正確的信息,這就是為什么開始說的臨時變量不能長時間使用
#include
#include"widget.h"
#include
#include
#include"database.h"
#include
#include
#include
intmain(intargc,char*argv[])
{
QApplicationapp(argc,argv);
QTextCodec*codec=QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
QFontfont;
font.setFamily(("WenQuanYiZenHei"));
font.setPointSize(12);
app.setFont(font);
app.setFont(font);
//if(!createConnection())
//return1;
QStringaaa="燈開kl";
QStringbbb="機頂盒的控制字";
QStringccc="頻道加";
#if0
QByteArrayba=aaa.toLatin1();
constchar*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);
QStringddd(c_str);
qDebug()<
#else
char*ad=aaa.toUtf8().data();
char*bb=bbb.toUtf8().data();
char*cc=ccc.toUtf8().data();
chara1[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));
intlen1=strlen(ad);
intlen2=strlen(bb);
//qDebug()<
#endif
QPushButtoncccc("AWQWQwq制熱");
cccc.show();
sqlite3*db;
char*zErrMsg;
sqlite3_stmt*stmt;
intCodec_Id=1;
if((sqlite3_open("room.db",&db))!=0){
qDebug()<
}
else{
qDebug()<
}
charsql3[100];
introom_Id=1;
intDevice_Id=1;
intDevice_Type=11;
intControl_Bty=11;
intControl_Status=1;
intncols,rc;
sprintf(sql3,"insertintoCodecvalues(%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);//檢查插入的數據有沒有問題
memset(sql3,0,sizeof(sql3));
sprintf(sql3,"select*fromCodec;");
intnrow=0,ncolumn=0;
char**azResult;//二維數組存放結果
sqlite3_get_table(db,sql3,&azResult,&nrow,&ncolumn,&zErrMsg);
inti=0;
//printf("size=%d\n",strlen(azResult));
printf("row:%dcolumn=%d\n",nrow,ncolumn);
printf("\nTheresultofqueryingis:\n");
for(i=0;i
printf("size=%dazResult[%d]=%s\n",strlen(azResult[i]),i,azResult[i]);
//釋放掉azResult的內存空間
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表示是燈的設備表的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)) ;
returnapp.exec();
}