波斯语中的QString

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并得到:

Notepad ++的快照 -

右侧的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)

testQPersian的快照

同样,作为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发送了以下快照:

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)
  1. 前两个字节从(解码大端16位整数)中提取readData并组合length.

  2. 其余部分dataRead转换为QString提供先前提取的length.从而,readData跳过前2个长度字节.