我非常好奇地等待回复,并自己玩了一下:
我复制了文字سلام
(英语:“Hello”)并将其粘贴到 Nodepad++(在我的例子中使用 UTF-8 编码)。然后我切换到查看十六进制并得到:
![snapshot of Notepad++ - hex dump of "سلام"](https://i.stack.imgur.com/VkdCd.png)
右侧的 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();
}
testQPersian.pro
:
SOURCES = testQPersian.cc
QT += widgets
编译并测试于cygwin在 Windows 10 上:
$ qmake-qt5 testQPersian.pro
$ make
$ ./testQPersian
![snapshot of testQPersian](https://i.stack.imgur.com/skW9U.png)
同样,Latin-1 的输出看起来与 OP 得到的以及 Notepad++ 公开的有点相似。
UTF-8 输出提供了预期的文本(正如预期的那样,因为我提供了正确的 UTF-8 编码作为输入)。
ASCII/Latin-1 输出的变化可能有点令人困惑。 – 存在多种字符字节编码,它们在下半部分(0 ... 127)共享 ASCII,但在上半部分(128 ... 255)具有不同的字节含义。 (看一下ISO/IEC 8859看看我的意思。在 Unicode 流行之前,这些已作为本地化引入final本地化问题的解决方案。)
波斯语字符肯定具有超过 127 个代码点的所有 Unicode 代码点。(Unicode 也共享前 128 个代码点的 ASCII。)此类代码点编码为UTF-8作为多个字节的序列,其中每个字节都设置了 MSB(最高有效位 - 位 7)。因此,如果这些字节(意外地)使用任何 ISO8859 编码进行解释,则上半部分变得相关。因此,根据当前使用的 ISO8859 编码,可能会产生不同的字形。
一些延续:
OP发送了以下快照:
![Snapshot (provided by OP)](https://i.stack.imgur.com/LHdpA.jpg)
所以,看起来而不是
d8 b3 d9 84 d8 a7 d9 85
he got
00 08 d8 b3 d9 84 d8 a7 d9 85
一种可能的解释:
服务器首先发送一个16位长度00 08
– 解释为大端字节序16 位整数:8, then 8以 UTF-8 编码的字节(看起来与我上面玩的一模一样)。
(AFAIK,如果发送方和接收方具有不同的字节顺序,那么使用 Big-Endian 进行二进制网络协议来防止字节顺序问题并不罕见。)这里:htons(3) - Linux 手册页
在 i386 上,主机字节顺序是最低有效字节在前,而 Internet 上使用的网络字节顺序是最高有效字节在前。
OP声称使用了该协议数据输出 – 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);
前两个字节是从readData
并结合到length
(解码大端 16 位整数)。
其余的dataRead
被转换为QString
提供之前提取的length
。因此,前 2 个长度字节readData
被跳过。