最近在做一个网络数据传输的项目,发现字节中带有大量0x00字节,发现如果用QString去表示,一般遇到0字符就直接结束了,经查明,这种带有0x00字节是因为Unicode编码格式表示的,Unicode是一种编码方式-百度百科
Unicode(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
经查寻到,QString类表示的数据内部就是使用Unicode编码方式,一个字符是由16位来表示的,对于低8位,与ASCII表示的一致,对于字符来说,高位的0x00如何获取到呢?
对于要发送的数据:“I Love China.”在网络上传送的用十六进制表示则是:[49 00 20 00 4C 00 6F 00 76 00 65 00 20 00 43 00 68 00 69 00 6E 00 61 00 2E 00]。以上是网络传输序列,事实上在本地我们只需转换如下 0x0049->0x00 0x49,对此我们可以通过以下方式来转换,
void QStringToMultiByte(const QString &reqmsg, QByteArray &request )
{
int size = reqmsg.size();
char* charArr = new char[size*2+10];
memcpy(charArr,reqmsg.toStdWString().c_str(),size*2);
request = QByteArray::fromRawData(charArr,size*2);
delete[] charArr;
charArr = NULL;
}
我们传入数据是QString表示的,通过将QString数据转成双字节的字符串,然后进行内存拷贝到charArr数组中,此时数组包含了大量的0x00这样的字节,然后通过fromRawData静态函数转换到QByteArray对象中。
接着我们就可以通过QTcpSocket中的write函数进行数据发送了。
//sock_m为QTcpSocket类的对象,msg为QByteArray类的对象,size等于msg.size().
sock_m->write(msg.data(),size);
if (!sock_m->waitForBytesWritten(1000))
{
return false;
}
else
return true;
那么返回的数据该如何转换成可读的字符串呢,即上面的反操作!
std::wstring MbsToWcs( const QByteArray& mbs )
{
int lengthOfWcs = mbs.size()/2 + 1;
wchar_t* wcs = new wchar_t[ lengthOfWcs ];
memcpy(wcs,mbs.data(),mbs.size());
std::wstring result = wcs;
delete[] wcs;
wcs = NULL;
return result;
}
void MultiByteToQString( const QByteArray& resp, QString& respstr )
{
// 0x00 0x12 -> 0x0012
std::wstring wstr = MbsToWcs(resp);
respstr = QString::fromStdWString(wstr);
}
也就是说,字节数组通过memcpy将数据拷贝搭到双字节数组中,然后给双字节类对象,最后通过QString静态函数fromStdWString转换成QString。