基于qt的嵌入式平台输入法:SYSZUXpinyin移植到arm后,UDP接收端中文乱码 本地中文乱码 解决

转自:  http://blog.csdn.net/yanzi1225627/article/details/7852326

SYSZUXpinyin输入法完全是用qt搭建的,移植到arm平台后,可以弹出软键盘,本人已成功。移植过程可以参考http://blog.chinaunix.net/uid-24219701-id-3077611.html这里,等有时间洒家写个移植的小细节。这里主要讲,移植后整个程序的文本、字符编码方式怎么调整才能避免乱码。

      我的环境是在Fedora14下,默认的编码方式是UTF-8,在未移植SYSZUX拼音之前,main函数里设置:

        QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));  //UTF-8
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));


       如此设置,UDP的接收端和发送端都可以正常显示中文。但SYSZUXpinyin采用的是GB2312方式,在主函数里必须设置  QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));  在弹出的软键盘里才能正常显示中文。值得交代的是,main函数里只需要加这一句就可以了,多加任何如QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));或者QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"))都会让软键盘显示异常!这块也是最纠结的地方.

       主函数里设成GB2312后,除了按钮上的汉字可以正常显示外,其他的如标题等都不能正常显示了。因为我们的linux下qt默认的中文环境是UTF-8格式,要正常显示中文必须转化成UTF-8格式。解决方法是:在widget.h里,#include <QTextCodec>,然后定义: QTextCodec *tc; 在widget.cpp的构造函数里:tc =  QTextCodec::codecForName("UTF-8"); 以后显示中文就用如: this->setWindowTitle(tc->toUnicode("Esto网络通讯模块----客户端"))来显示!

      奇怪的是本地EditText是可以正常显示的,如ui->getTextEdit->insertPlainText( sendStr +"\n");操蛋就操蛋在发送端和接收端。在对端上中文都是乱码。我原以为tr设成GB2312后,对CStrings默认的也成了GB2312.既然发送端是GB2312,我曾实验发送端GB2312-----------接收端GB2312解析,显示出来还是乱码。将解析的GB2312再转成UTF-8还是乱码,郁闷我一个下午,几乎近于崩溃!后来我意识到,这个想当然cstrings的编码格式是错误的。

       后来用QtCreator的帮助手册,问题出在udp的发送函数 在发送之前将QString转成QByteArray,   

   
   QString sendStr = ui->sendTextEdit->toPlainText();
    QByteArray sendByteArray  = sendStr.toAscii();

      这里是通过.toAscii()方式转换的。转换时依据的编码方式就是setCodecForCStrings设的值,看下手册上咋说的:

QByteArray QString::toAscii () const
Returns an 8-bit representation of the string as a QByteArray.

If a codec has been set using QTextCodec::setCodecForCStrings(), it is used to convert Unicode to 8-bit char; otherwise this function does the same as toLatin1().

默认的是采用toLatin1()转换的,所以接受端无论按GB2312还是UTF-8怎么转都是乱码。而在主函数里又不能设定全局的setCodecForCStrings的编码方式。所以我最初尝试在send函数发送前,setCodecForCStrings()设成UTF-8,然后发送完后再将setCodecForCStrings()设成GB2312,发现只有第一次能发送中文,对端能正常显示。以后软键盘就乱码了。问题的根源在这里,SYSZUXpinyin的tr编码方式是GB2312,而setCodecForCStrings()这里应该是默认值,默认值多少呢?再看手册:

void QTextCodec::setCodecForCStrings ( QTextCodec * codec ) [static]
Sets the codec used by QString to convert to and from const char * and QByteArrays. If the codec is 0 (the default), QString assumes Latin-1.

默认的是Latin-1格式,也就是将codec设成0就恢复到默认状态了。用这个思路改,应该也能成功!

      其实,问题的症结在toAscii()的时候依据的编码格式,能够在toAscii()之前,将QString转成UTF-8不就好了么。

将这句话QByteArray sendByteArray  = sendStr.toAscii();改成QByteArray sendByteArray = sendStr.toUtf8().data();UDP的显示消息模块不变,依然用 

QTextCodec *tutf=QTextCodec::codecForName("UTF-8");
QString dataStr =tutf->toUnicode(data);
还用UTF-8来解析,这样就能正常接收消息并显示中文了!


       我后来又实验了上面的思路,在执行QByteArray sendByteArray  = sendStr.toAscii(); 这句话之前,将setCodecForCStrings通过QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));设为UTF-8格式,在UDP发送函数的末尾加上,QTextCodec::setCodecForCStrings(0);将编码方式设为0,也就是默认的 Latin-1.格式,经过测试,一切正常!两种方法都可以。接收函数保持不变。

我将udp部分的send函数和receive函数贴下,大家看完整的可以看我以前的帖子:

[html]  view plain copy print ?
  1. <span style="font-size:18px;">void Widget::send()  
  2. {  
  3.     autoScroll();  
  4.     QString sendStr = ui->sendTextEdit->toPlainText();  
  5.  <u><span style="color:#ff0000;">    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));  
  6.     QByteArray sendByteArray  = sendStr.toAscii();</span></u>  
  7.   
  8.    // QByteArray sendByteArray = sendStr.toUtf8().data(); //为了配合SYSZUXpinyin输入法,这种方法也可以  
  9.     QMessageBox box;  
  10.     if(sendStr.length()==0)  
  11.     {  
  12.         box.setText(tc->toUnicode("请输入发送内容"));  
  13.         box.exec();  
  14.     }  
  15.     else if(configFlag)  
  16.     {  
  17.   
  18.         udpSocket1->writeDatagram(sendByteArray, sendByteArray.length(), *remoteHostAddr, 6665);  
  19.   
  20.         //本地发送信息再信息交互窗口的显示  
  21.         QDateTime time;  
  22.         QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");  
  23.         ui->getTextEdit->setTextColor(QColor("red"));  
  24.   
  25.         ui->getTextEdit->insertPlainText(tc->toUnicode("本机") + localIpStr + ": " + timeStr + "--UDP--\n");  
  26.         ui->getTextEdit->setTextColor(QColor("black"));  
  27.         ui->getTextEdit->insertPlainText( sendStr +"\n");  
  28.         ui->sendTextEdit->clear();          //点击发送后,发送编辑框内清零  
  29.         ui->sendTextEdit->setFocus();   //焦点停留在发送编辑框  
  30.         autoScroll();  
  31.     }  
  32.     else if(!configFlag)  
  33.     {  
  34.         box.setText(tc->toUnicode("请您先点击确认按钮!"));  
  35.         box.exec();  
  36.     }  
  37.       <u><strong><span style="color:#ff0000;">QTextCodec::setCodecForCStrings(0);//为了让移植的SYSZUXpin软键盘中文显示正常,必须让CStrings恢复到默认的Latin-1编码格式</span></strong></u>  
  38. }  
  39. void Widget::receive()  
  40. {  
  41.     while(udpSocket1->hasPendingDatagrams())  
  42.     {  
  43.         autoScroll();        
  44.         QTextCodec *tutf=QTextCodec::codecForName("UTF-8");  
  45.         QDateTime time;  
  46.         QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");  
  47.   
  48.         QByteArray data;  
  49.         data.resize(udpSocket1->pendingDatagramSize());  
  50.         udpSocket1->readDatagram(data.data(), data.size());  
  51.               //QString dataStr =  QString::fromUtf8(data.data());   //这样写也是正确的      
  52.         
  53.         QString dataStr =tutf->toUnicode(data);  
  54.         ui->getTextEdit->setTextColor(QColor("red"));  
  55.         ui->getTextEdit->insertPlainText(tc->toUnicode("远程")  + remoteIpStr+": "+ timeStr +"--UDP--\n" );  
  56.         ui->getTextEdit->setTextColor(QColor("black"));  
  57.         ui->getTextEdit->insertPlainText(dataStr  + "\n" );  
  58.         autoScroll();  
  59.   
  60.     }</span>  

总结下:

1,SYSZUXpinyin官方只说是用GB2312编码,实际没有说全,他的tr要设成GB2312,而CStrings不用设,保留默认,其实是QString默认的Latin-1格式。而这个格式直接影响QString转QByteArray的编码格式,这个格式搞不对,在接收端就像没娘的熊瞎子,乱试就是显示不了正常的中文。


2,QString与QByteArray的转换


QString string;
QByteArray data; 
data = string.toAscii();   //按照setCodecForCStrings()的格式进行转换

sendStr.toLatin1().data(); //如果转换格式未设置,则上面的转换等同于此,即按默认的Latin1格式转换
data = string.toUtf8().data(); //按UTF-8格式

QByteArray转QString:


QByteArray encodedString = "xxx";
QTextCodec *tc = QTextCodec::codecForName("UTF-8");
QString string = tc->toUnicode(encodedString);


3,其实现在我们再想想,如果UDP发送端对setCodecForCStrings不设UTF-8,

直接data = string.toAscii(); 让他按照默认的setCodecForCStrings()方式Latin-1进行转。

在接收方得到QByteArray之后,按照QTextCodec *tc = QTextCodec::codecForName("Latin1");

进行转换QString,得到Latin1编码格式的QString,再对QString的data数据进行UTF-8转换,

应该也能正常显示中文!


       结论:

         移植SYSZUXpinyin的注意了,为了让SUSZUXpinyin的软键盘正常拼出中文,

CStrings的编码格式一定要设成默认的Latin1格式,同时tr设成GB2312.

        看来我们解决问题,一定要理清头绪,多看软件的英文参考文档,

从原理出发去解决,往往事半功倍!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值