字符编码问题详解: http://blog.csdn.net/bluetjs/article/details/52936943
http://blog.csdn.net/u010737354/article/details/52456570
http://www.360doc.com/content/12/0423/17/9470897_205933736.shtml
http://www.bangnishouji.com/tools/chtounicode.html
http://www.2cto.com/kf/201604/503757.html
下面是对上面网址的试验理解:
使用UNICODE字符集:
int t1=sizeof(TCHAR); 2
int t2=sizeof(CHAR); 1
使用多字节字符集:
int t1=sizeof(TCHAR); 1
int t2=sizeof(CHAR); 1
未设置:
int t1=sizeof(TCHAR); 1
int t2=sizeof(CHAR); 1
从父级或项目默认设置继承:
int t1=sizeof(TCHAR); 1
int t2=sizeof(CHAR); 1
以 CreateFile 为例 不同的字符集设置,要使用不同的函数 : 不同函数处理方式不一样 有些是这样,有些不是这样
#ifdef UNICODE // 相等于 设置中勾选 使用UNICODE字符集:
#define CreateFile CreateFileW
#else
#define CreateFile CreateFileA
#endif // !UNICODE
CreateFileW(
__in LPCWSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile
);
CreateFileA(
__in LPCSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile
);
比较 CreateFileW CreateFileA 发现 第一个参数 lpFileName, 的类型不一样,LPCWSTR LPCSTR 可见编码格式对它的影响。
因为我是下面联调,我把数据 透传给下层,后来直接用的 std::string QString::toStdString() ,在QT中中文显示 是乱码,但是在下层中文可以正常显示,所以,如果 你的代码是联调,一定要先测试一下,再决定 哈,不然你转半天,发现透传到下层程序 又好了!!!
参考
http://blog.csdn.net/libaineu2004/article/details/19245205
http://blog.csdn.net/brave_heart_lxl/article/details/7186631
后来上面2个帖子里面的内容都没有用上,不过 还是要谢谢他们 !!!
下面是我自己的解决方案:
QJsonValue name_value = obj.take(QObject::tr("serviceCNName"));
if(name_value.isString())
{
QString strTT;
strTT = name_value.toString(QObject::tr(""));;//中文非乱码 内容为 测试中文代码 ,共6个汉字 ---- 解决方案
int lent5=strTT.length();//6
serviceCNName=strTT.toStdString();//乱码
int lent6=serviceCNName.length();//18
QByteArray ba = strTT.toLocal8Bit();//中文非乱码 ---- 解决方案
int lent7=ba.length();//12
serviceCNName=ba.toStdString();//中文非乱码 --- 解决方案
int lent8=serviceCNName.length();//12
const QChar * p2= strTT.unicode() ;
QString strt1;
strt1.append(p2, strTT.length());//中文非乱码
int lent9=strt1.length();//6
//test code b
QByteArray ba8=strTT.toUtf8();//乱码
int lent10=ba8.length();//18
string str8=ba8.toStdString();//乱码
int lent11=str8.length();//18
std::wstring wstr8=strTT.toStdWString();//中文非乱码
int lent12=wstr8.length();//6
std::string str8std=strTT.toStdString();//乱码
int lent13=str8std.length();//18
//std::u16string str16=QString::toStdU16String();
const QChar * p1= strTT.unicode();
int lent1=strTT.length();//6
QString strt2=strTT.setUnicode(p1, lent1);//中文非乱码
int lent2=strt2.length();//6
string sstrt1=strt2.toStdString();//乱码
int lent3=sstrt1.length();//18
wstring sstrt2=strt2.toStdWString();//中文非乱码
int lent4=sstrt2.length();//6
//test code e
//serviceClassStr=name_value.toString(QObject::tr(""));
//QString::toLocal8Bit()
//serviceClass=ba.toStdString();
//serviceCNName=strTT.toStdWString() ;
}
下面贴一段WSTR转换为单STR 的代码:以供以后遇到 这样的问题时的参考:
void W2C(const wchar_t *pw , char *pc)
{
*pc++ = (*pw)& 0xFF;
*pc = (*pw)>>8;
}
char *wstr2cstr(const wchar_t *pwstr , char *pcstr)
{
char *ptemp = pcstr ;
if(pwstr!=NULL && pcstr!=NULL)
{
size_t wstr_len = wcslen(pwstr) ;
while( wstr_len -- > 0)
{
W2C(pwstr , pcstr);
pwstr++ ;
pcstr +=2 ;
}
*pcstr = '\0';
return ptemp ;
}
return 0 ;
}
附录:我目前是在QT551 里面用,后台 用的是JAVA和C++程序 ,JAVA过来的数据包是JSON格式的,是UNICODE编码,C++下面是标准的string函数,在所有的数据接口中,不建议用QString,因为它会在不同的QT版本中有不同的函数,所以外部数据接口一律用标准的string,另外,这只是 在WINDOWS下面的调试通过 ,LINUX下面这些QT代码还没有调试。等LINUX调试了再说明LINUX的代码说明,须知。
把代码保存方式存储为 UTF-8,下面是代码:
QString testQstring1=QString::fromLocal8Bit("系统服务");
QString testQstring2=QString::fromLocal8Bit("系统服务"); --- 中文可以正确显示
int len1=testQstring1.length();
string s1=testQstring1.toStdString();
int len2=s1.length();
QByteArray ba=testQstring1.toLocal8Bit();
int len3=ba.length();
int c1=testQstring1.compare(tr("系统服务")); -- 不相等
int c2=testQstring1.compare(testQstring2); -- 相等
参见 QTextCodec 例子地址:
QTextCodec 例子: E:\Qt\Qt5.5.1\Examples\Qt-5.5\widgets\tools\codecs\codecs.pro
可以把此例子运行起来,自己写些中文上去,看看不同的编码出来是什么结果
"UTF-8" 106
"ISO-8859-1" 4
"ISO-8859-15" 111
"UTF-32LE" 1019
"UTF-32BE" 1018
"UTF-32" 1017
"UTF-16LE" 1014
"UTF-16BE" 1013
"UTF-16" 1015
"System" 0
"Big5-HKSCS" 2101
"Big5" 2026
"windows-949" -949
"EUC-KR" 38
"Shift_JIS" 17
"ISO-2022-JP" 39
"EUC-JP" 18
"GB2312" 2025
"GBK" 113
"GB18030" 114
"hp-roman8" 2004
"TIS-620" 2259
"WINSAMI2" -165
"macintosh" 2027
"windows-1258" 2258
"windows-1257" 2257
"windows-1256" 2256
"windows-1255" 2255
"windows-1254" 2254
"windows-1253" 2253
"windows-1252" 2252
"windows-1251" 2251
"windows-1250" 2250
"IBM866" 2086
"IBM874" -874
"IBM850" 2009
"ISO-8859-16" 112
"ISO-8859-14" 110
"ISO-8859-13" 109
"ISO-8859-10" 13
"ISO-8859-9" 12
"ISO-8859-8" 85
"ISO-8859-7" 10
"ISO-8859-6" 82
"ISO-8859-5" 8
"ISO-8859-4" 7
"ISO-8859-3" 6
"ISO-8859-2" 5
"KOI8-U" 2088
"KOI8-R" 2084
"iscii-mlm" -3008
"iscii-knd" -3007
"iscii-tlg" -3006
"iscii-tml" -3005
"iscii-ori" -3004
"iscii-gjr" -3003
"iscii-pnj" -3002
"iscii-bng" -3001
"iscii-dev" -3000
"TSCII" 2107
// const char *name1="GB2312";
//// QTextCodec *codecdes = QTextCodec::codecForName(QObject::tr("GB2312"));
//// QTextCodec *codecdes = QTextCodec::codecForMib(2025);//! GB2312
// QTextCodec *codecdes = QTextCodec::codecForMib(106);//! "UTF-8" 106
// QByteArray encodedData=serviceClass.toLatin1();
// QTextStream in(&encodedData);
// in.setAutoDetectUnicode(false);
// in.setCodec(codecdes);
// QString decodedStr = in.readAll();
// int i=90;
下面是用QT的语言专家来解决的QT中的中文问题,方法如下:
先在工程PRO中
TRANSLATIONS+=abcd.ts
然后QMAKE, xxxx.png
更新编译,然后再打开QT语言专家,在语言专家中可以看到你的类,类下面的所有以tr()开关的字符串---注意:所有要翻译的字符串,代码中必须用 英文 来写,然后翻译的时候,翻译成中文,然后翻译好后,点击保存,发布,再在代码的MAIN.cpp中添加如下代码:
#include
QTranslator *tr = new QTranslator;
tr->load("../demos/xxx/ttt/xxx.qm");
app.installTranslator(tr);
可以把这个生成的ts文件添加到工程中,每次翻译后,都要保存,发布
也可以对界面上的进行翻译 ,同样的原理 界面上有一个属性,可翻译的,就表示这个意思 (tr)
下面是另外一
LangSwitch.h:
#ifndef LangSwitch_H
#define LangSwitch_H
#include
#include
#include
class LangSwitch : public QWidget
{
Q_OBJECT
public:
LangSwitch(QWidget *parent = 0);
~LangSwitch();
private slots:
void changeLang(int indexx);
private:
void createScreen();
void changeTr(const QString & langCode);
void refreshLabel();
QComboBox* combo;
QLabel *label;
};
#endif // MAINWINDOW_H
LangSwitch.cpp:
#include "LangSwitch.h"
#include
#include
#include
#include
LangSwitch::LangSwitch(QWidget *parent) :
QWidget(parent)
{
createScreen();
}
LangSwitch::~LangSwitch()
{
}
void LangSwitch::changeLang(int indexx)
{
QString langCode=combo->itemData(indexx).toString();
changeTr(langCode);
refreshLabel();
}
void LangSwitch::createScreen()
{
combo=new QComboBox;
combo->addItem("English","en");
combo->addItem("Chinese","zh");
combo->addItem("Latin","la");
label=new QLabel;
refreshLabel();
QVBoxLayout *layout=new QVBoxLayout;
layout->addWidget(combo,1);
layout->addWidget(label,5);
setLayout(layout);
connect(combo,SIGNAL(currentIndexChanged(int)),this,SLOT(changeLang(int)));
}
void LangSwitch::changeTr(const QString &langCode)
{
static QTranslator *translatort;
if(translatort!=NULL)
{
qApp->removeTranslator(translatort);
delete translatort;
translatort=NULL;
}
translatort=new QTranslator;
QString qmFilename="lang_"+langCode;
QString ss=QDir::currentPath();//E:\delcode\build-untitled-Desktop_Qt_5_5_1_MSVC2010_32bit_qt_55_w-Debug
//if(translatort->load(QString("../")+qmFilename))
if(translatort->load(qmFilename))//详见load的说明,首先加载 的是ss中的 .qm 文件 所以要更新,还要发布 其实所有的qm文件是同一份,会对应不同的数据 取值
{
qApp->installTranslator(translatort);
}
}
void LangSwitch::refreshLabel()
{
label->setText(tr("TXT_HELLO_WORLD","Hello World"));// Hello World 出现在开发人员注释那里,这样可以给开发人员提醒。
}
有些代码中是不基于QObject 的,下面是代码中的解决方案,以及图:
class xx
{
public:
Q_DECLARE_TR_FUNCTIONS(xx)
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//! TRANSLATIONS+=$$PWD/debug/win.ts
QTranslator trX;
QString strdir = QCoreApplication::applicationDirPath();
QString qmStr = strdir+"/win.qm";
trX.load(qmStr);
a.installTranslator(&trX);
QTextStream errorStream(stderr);
if (argc != 2)
{
QString s = xx::tr( "Usage: xmlstreamlint ");
errorStream << s;
return 2;
}
return a.exec();
}
图: