波斯语中的QString

时间:2018-08-25 14:07:51

标签: c++ qt text decoding

我给出了一个Qt项目,该项目需要支持波斯语。从服务器发送数据并使用第一行,我得到一个QByteArray并使用第二行将其转换为QString:

function playerStart() {

var widget = Mixcloud.PlayerWidget(document.getElementById("mmnMixPlayer"));
    widget.ready.then(function() {
        // Put code that interacts with the widget here
        play();
    });

 /* AJAX link click */
jQuery(document).on("click", "a[target!='_blank']:not(a[href^='#'])", function(e){
    var link = jQuery(this).attr("href");
    // var title = jQuery(responseHtml).filter('title').text();
    // console.log(title);
    jQuery("#content").load( link + " #content", function(responseText) {
      var newtitle = escapeHtml(responseText.match(/<title>([^<]*)/)[1]);
      document.title = newtitle; } 
    );
    e.preventDefault();
    history.pushState({}, null, link);
    // jQuery(document).find("title").text(jQuery(responseHtml).filter('title').text());
});

}

function playerStop() {

var widget = Mixcloud.PlayerWidget(document.getElementById("mmnMixPlayer"));
    widget.ready.then(function() {
        // Put code that interacts with the widget here
        pause();
    });

}


jQuery(document).on("click", "#listengomb.stopped", function(e){
    playerStart();
    jQuery(this).removeClass("stopped").addClass("playing");
    e.preventDefault;
}) 

jQuery(document).on("click", "#listengomb.playing", function(e){
    playerStop();
    jQuery(this).removeClass("playing").addClass("stopped");
    e.preventDefault;
})  

以英语发送数据时,一切都很好,但是以波斯语代替

    QByteArray readData = socket->readAll();
    QString DataAsString = QTextCodec::codecForUtfText(readData)->toUnicode(readData);

我知道

سلام

我提到了此过程,因此人们不会建议使用.tr的多语言应用程序的制作方法。都是关于文本和解码的,而不是那些翻译方法。我的操作系统是Windows 8.1(对于您需要了解的情况)。

当服务器发送سلام

时,我得到这个十六进制值
سÙ\u0084اÙ\u0085

由于我不知道的原因,通过服务器的方式在开头发送了两个额外的字节。所以我用以下方法切断了它:

0008d8b3d984d8a7d985

在将其转换为QString之后,十六进制值在开始时会有一些额外的作用。

2 个答案:

答案 0 :(得分:7)

我对等待回复感到好奇,并独自开玩笑:

我复制了文本سلام(英语:“ Hello”),并将其粘贴到Nodepad ++(在我的情况下使用UTF-8编码)。然后我切换到以十六进制查看并得到:

snapshot of Notepad++ - hex dump of "سلام"

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

已在Windows 10的cygwin中进行了编译和测试:

$ qmake-qt5 testQPersian.pro

$ make

$ ./testQPersian

snapshot of testQPersian

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

enter image description here

所以,似乎代替了

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 man page

  

在i386上,主机字节顺序是最低有效字节在前,而在Internet上使用的网络字节顺序是最高有效字节在前。


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);
  1. 前两个字节是从readData中提取出来的,并组合到length中(解码大尾数16位整数)。

  2. dataRead的其余部分将转换为QString,提供先前提取的length。因此,readData的前2个长度字节被跳过。

答案 1 :(得分:0)

您需要像这样用utf8发送数据

    mysocket->write(message.toUtf8());

并像这样接收并转换为utf8:

    QByteArray Data = mysocket->readAll();
    QString DataAsString = QString::fromUtf8(Data);

您的数据将被发送而不会变得无法识别