ste*_*etz 8 c++ qt text decoding
我给了Qt的项目,该项目需要支持波斯language.T他的数据从服务器发送和使用的第一线,我得到一个QByteArray中,并使用第二线将其转换为QString的:
QByteArray readData = socket->readAll();
QString DataAsString = QTextCodec::codecForUtfText(readData)->toUnicode(readData);
Run Code Online (Sandbox Code Playgroud)
当数据发送是英文时,一切都很好,但是当它是波斯语时,而不是
????
Run Code Online (Sandbox Code Playgroud)
我明白了
سÙ\u0084اÙ\u0085
Run Code Online (Sandbox Code Playgroud)
我提到了这个过程,所以人们不会建议制作使用.tr的多语言应用程序的方法.所有关于文本和解码都不是那些翻译方法.我的操作系统是Windows 8.1(对于你需要知道它的情况).
当服务器发送سلام时,我得到这个十六进制值
0008d8b3d984d8a7d985
Run Code Online (Sandbox Code Playgroud)
顺便说一句,服务器在开始时发送两个额外的字节,原因我不知道.所以我用以下方法切断它:
DataAsString.remove(0,2);
Run Code Online (Sandbox Code Playgroud)
在它被转换为QString之后,十六进制值在乞讨时有一些额外的.
感谢您阅读我的帖子.
Sch*_*eff 10
我很想等待回复并自己玩弄一下:
我复制了文本????(英文:"Hello")并将其粘贴到Nodepad ++(在我的情况下使用UTF-8编码).然后我切换到View as Hex并得到:
右侧的ASCII转储看起来有点类似于意外的OP.这让我相信字节readData是以UTF-8编码的.因此,我采用了暴露的十六进制数字并制作了一些示例代码:
testQPersian.cc:
#include <QtWidgets>
int main(int argc, char **argv)
{
QByteArray readData = "\xd8\xb3\xd9\x84\xd8\xa7\xd9\x85";
QString textLatin1 = QString::fromLatin1(readData);
QString textUtf8 = QString::fromUtf8(readData);
QApplication app(argc, argv);
QWidget qWin;
QGridLayout qGrid;
qGrid.addWidget(new QLabel("Latin-1:"), 0, 0);
qGrid.addWidget(new QLabel(textLatin1), 0, 1);
qGrid.addWidget(new QLabel("UTF-8:"), 1, 0);
qGrid.addWidget(new QLabel(textUtf8), 1, 1);
qWin.setLayout(&qGrid);
qWin.show();
return app.exec();
}
Run Code Online (Sandbox Code Playgroud)
testQPersian.pro:
SOURCES = testQPersian.cc
QT += widgets
Run Code Online (Sandbox Code Playgroud)
在Windows 10上的cygwin中编译和测试:
$ qmake-qt5 testQPersian.pro
$ make
$ ./testQPersian
Run Code Online (Sandbox Code Playgroud)
同样,作为Latin-1的输出看起来有点类似于OP得到的以及Notepad ++暴露的内容.
输出为UTF-8提供了预期的文本(正如预期的那样,因为我提供了正确的UTF-8编码作为输入).
可能是,ASCII/Latin-1输出变化有点令人困惑. - 存在多个字符字节编码,它们在下半部分(0 ... 127)共享ASCII,但在上半部分(128 ... 255)具有不同的字节含义.(看看ISO/IEC 8859,看看我的意思.在Unicode成为本地化问题的最终解决方案之前,已经将这些作为本地化引入.)
波斯语字符肯定有超过127的所有Unicode代码点.(Unicode也为前128个代码点共享ASCII.)此类代码点以UTF-8编码为多个字节的序列,其中每个字节都有MSB(最重要的位 -第7位)设置.因此,如果使用任何ISO8859编码(意外地)解释这些字节,则上半部分变得相关.因此,根据当前使用的ISO8859编码,这可能产生不同的字形.
一些延续:
OP发送了以下快照:

所以,它似乎而不是
d8 b3 d9 84 d8 a7 d9 85
他有
00 08 d8 b3 d9 84 d8 a7 d9 85
可能的解释:
服务器首先发送一个16位长度00 08- 解释为Big-Endian 16位整数:8,然后8个字节以UTF-8编码(看起来与我上面播放的那个完全一样).(AFAIK,如果发送方和接收方具有本地不同的字节顺序,使用Big-Endian来实现二进制网络协议以防止字节序问题并不罕见.)进一步阅读,例如:htons(3) - Linux手册页
在i386上,主机字节顺序首先是最低有效字节,而在因特网上使用的网络字节顺序是最高有效字节.
OP声称此协议使用DataOutput - writeUTF:
将两个字节的长度信息写入输出流,然后是字符串s中每个字符的修改后的UTF-8表示.如果s为null,则抛出NullPointerException.字符串s中的每个字符都将转换为一个,两个或三个字节的组,具体取决于字符的值.
因此,解码可能如下所示:
QByteArray readData("\x00\x08\xd8\xb3\xd9\x84\xd8\xa7\xd9\x85", 10);
//QByteArray readData = socket->readAll();
unsigned length
= ((uint8_t)readData[0] << 8) + (uint8_t)readData[1];
QString text = QString::fromUtf8(dataRead.data() + 2, length);
Run Code Online (Sandbox Code Playgroud)
前两个字节从(解码大端16位整数)中提取readData并组合length.
其余部分dataRead转换为QString提供先前提取的length.从而,readData跳过前2个长度字节.