Мне было очень любопытно дождаться ответа, и я немного поиграл:
Я скопировал текст سلام
(на английском языке: "Hello") и вставил его в Nodepad ++ (который использовал UTF).-8 кодировка в моем случае).Затем я переключился на View as Hex и получил:
![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)
Снова вывод в виде латиницы1 выглядит немного похожим на то, что получил OP, а также на то, что показал Notepad ++.
Вывод в виде UTF-8 обеспечивает ожидаемый текст (как и ожидалось, потому что я предоставил правильную кодировку UTF-8 в качестве ввода).
Может быть, немного странно, что выходные данные ASCII / Latin-1 различаются.- Существует несколько кодировок байтов символов, которые разделяют ASCII в нижней половине (0 ... 127), но имеют различные значения байтов в верхней половине (128 ... 255).(Посмотрите на ISO / IEC 8859 , чтобы понять, что я имею в виду. Они были введены в качестве локализаций до того, как Unicode стал популярным как окончательное решение проблемы локализации.)
Персидские символы, безусловно, имеют все кодовые точки Unicode, кроме 127. (Unicode разделяет ASCII и для первых 128 кодовых точек.) Такие кодовые точки кодируются в UTF-8 как последовательности из нескольких байтов, где каждый байтимеет MSB (самый старший бит - бит 7).Следовательно, если эти байты (случайно) интерпретируются с использованием любой кодировки ISO8859, тогда верхняя половина становится релевантной.Таким образом, в зависимости от используемой в настоящее время кодировки ISO8859 это может привести к различным символам.
Некоторое продолжение:
OP отправил следующий снимок:
![enter image description here](https://i.stack.imgur.com/LHdpA.jpg)
Итак, кажется, вместо
d8 b3 d9 84 d8 a7 d9 85
он получил
00 08 d8 b3 d9 84 d8 a7 d9 85
AВозможная интерпретация:
Сервер отправляет сначала 16-битную длину 00 08
- интерпретируется как Big-Endian 16-битное целое число: 8 , затем 8 байтов, закодированных в UTF-8 (которые выглядят точно так же, как тот, что я получил, играя выше).(AFAIK, нередко использовать Big-Endian для двоичных сетевых протоколов, чтобы предотвратить проблемы с порядком байтов, если отправитель и получатель имеют изначально разные порядковые номера байтов.) Дополнительная информация, например, здесь: htons (3) - страница руководства Linux
На i386 порядок байтов хоста - сначала Наименьший значащий байт, тогда как порядок байтов в сети, используемый в Интернете, - наибольший значащий байт вначале.
OP утверждает, что этот протокол используется DataOutput - writeUTF :
Записывает два байта информации о длине в выходной поток, за которым следует измененное представление 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
пропускаются.