2

Here is HttpServer in JAVA, that sends russian string to Qt application:

 public void handle(HttpExchange t) throws IOException {
        //Response from server in Russian
        String response = "Ответ от сервера на русском языке"; //"Response from server in Russian"
        t.sendResponseHeaders(200, response.length());
        OutputStream os = t.getResponseBody();
        //os.write(response.getBytes());
       //right now I am trying this code
      os.write(response.getBytes(Charset.forName("UTF-8"))); //and UTF-16
       //also I have tried this
        os.write(Charset.forName("UTF-16").encode(response).array());

        os.close();
    }

Application in Qt gets response from server (text in russian)

 void MainWindow::Response(QNetworkReply *reply) {
    QByteArray data = reply->readAll();
   // Also I've tried this
   // QString dataString = (QString)reply->readAll();
   // QString dataLine = (QString)reply->readLine();
   // QString str=  QString::fromUtf8(data);
    qDebug() << "data from server: " << data;
     label->setText(str);
} 

I just want to show normal string in console or in label component, but I have empty string or array of bytes or sequence of question marks

"\xCE\xF2\xE2\xE5\xF2 \xEE\xF2 \xF1\xE5\xF0\xE2\xE5\xF0\xE0 \xED\xE0 \xF0\xF3\xF1\xF1\xEA\xEE\xEC \xFF\xE7\xFB\xEA\xE5"

How can I solve this problem with encoding and convert this array to QString and finally see the normal text ?

Dmitry
  • 23
  • 1
  • 5

1 Answers1

3

getBytes

public byte[] getBytes()

Encodes this String into a sequence of bytes using the platform's default charset, storing the result into a new byte array.

The behavior of this method when this string cannot be encoded in the default charset is unspecified. The CharsetEncoder class should be used when more control over the encoding process is required.

Using this method to serialize the string is a terrible idea; the "platform default encoding" depends from current locale, operating system and whatnot, while you want a well-defined encoding to transmit data between applications.

In facts, I trust you when you say "I've tried everything, nothing works" - that's because your string is encoded in the windows-1251 encoding, which probably happens to be the default 8-bit encoding of your Windows machine. When you try to decode it on the Qt side - which, from Qt5, always expects UTF-8 by default when decoding 8-bit strings, everything breaks.


First of all, on the Java side encode your string in UTF8, making sure to specify the response length correctly (you have to provide the number of bytes you are writing, not of characters in the source string):

String response = "Ответ от сервера на русском языке"; //"Response from server in Russian"
byte[] response_data = response.getBytes("UTF-8");
t.sendResponseHeaders(200, response_data.length());
OutputStream os = t.getResponseBody();
os.write(response_data);
os.close();

Then, on the Qt side, you can build a QString from the QByteArray, specifying it's in UTF8.

QByteArray data = reply->readAll();
QString str = QString::fromUtf8(data);

(notice that you may send your string in UTF-16 or UTF-32 as well, but of course the two sides must match; I chose UTF-8 because it's way more common as an "on the wire" format and because it's generally more compact)

Community
  • 1
  • 1
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • hey, thanks for your answer, I understand now, but there is a little problem OutputStream os.write() can not accept Charset.forName("UTF-8").encode(response) I have tried with Channels but it doesn't work http://stackoverflow.com/a/579616/7823223 – Dmitry Apr 05 '17 at 22:00
  • "can not accept" has no meaning... what error do you get? Did you do `import java.nio.charset.Charset;`? – Matteo Italia Apr 05 '17 at 22:04
  • Seems a little odd to convert to and from UTF-8, since both Java and Qt use UTF-16 encoding. – MrEricSir Apr 05 '17 at 22:09
  • Of course I imported that library. The method write(int) in the type OutputStream is not applicable for the arguments (ByteBuffer). I've tried to apply method array(): os.write(Charset.forName("UTF-8").encode(response).array()); but I get emptry string in Qt client – Dmitry Apr 05 '17 at 22:13
  • [Channels seem to be the way to go](http://stackoverflow.com/questions/579600/how-to-put-the-content-of-a-bytebuffer-into-an-outputstream), or you can get a byte array [like this](http://stackoverflow.com/questions/679298/gets-byte-array-from-a-bytebuffer-in-java). Sorry but I never worked in Java, so my suggestions may be a bit off on that side. – Matteo Italia Apr 05 '17 at 22:36
  • @MrEricSir: and just think that every integer in network protocols travels in big endian, while virtually every machine is little endian; at least in this case there's a distinct advantage (UTF-8 being generally more compact than UTF-16). – Matteo Italia Apr 05 '17 at 22:38
  • Oh gosh, there's another overload of the `getBytes` that takes the encoding as a parameter and returns a `byte[]`; it was way simpler than all this `ByteBuffer` mess. :-) – Matteo Italia Apr 05 '17 at 22:39
  • I have just tried this os.write(response.getBytes("UTF-8")); but I still get empy string in qt, I am desperate with this :( So simple task - just send response, with English text everything works well – Dmitry Apr 05 '17 at 22:48
  • Is it failing to encode, to decode or to transmit? If you write out the byte array on the Java side is it sane? What do you get in the `QByteArray` on the Qt side? Also, you'll quickly learn that there's no such a thing as a "simple task" when dealing with text and encodings. – Matteo Italia Apr 05 '17 at 22:52
  • It is failing to decode in qt, I tried this os.write(response.getBytes("UTF-16")); (also UTF-8) and in qt QString str1 = QString::fromUtf16(reinterpret_cast(data.constData()), 10); and QString str2 = QString::fromUtf8(data); Convertation fromutf16 gives this = "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\uFFFF\uFFFF" – Dmitry Apr 05 '17 at 22:55
  • Again, what do you get if you do `qDebug()< – Matteo Italia Apr 05 '17 at 22:57
  • qDebug() << data; gives "" -empty – Dmitry Apr 05 '17 at 22:58
  • Well of course if you did `response.getBytes("UTF-16")`... use UTF-8. If it still gives you an empty string, check what you are sending on the java side (dump `response.getBytes("UTF-8")`). – Matteo Italia Apr 05 '17 at 23:00
  • If I send text in English - everything is alright in qt, I get it, but the same doesn't work with russian text, it is like magic – Dmitry Apr 05 '17 at 23:02
  • Please update the post with the current code, I can't understand what you are testing now. – Matteo Italia Apr 05 '17 at 23:07
  • Ok, now, I see that in the example above you call `Charset.forName("UTF-16").encode(response).array()` - don't do that, `.array()` is not guaranteed to return anything meaningful, and UTF-16 is not what we are after. Use the straight `os.write(response.getBytes("UTF-8"))`. What do you get with `qDebug()< – Matteo Italia Apr 05 '17 at 23:15
  • QByteArray data = reply->readAll(); data.size() = 0, it is really weird, because if I send text in English - it works and data is NOT null I tested with this java code: os.write(response.getBytes("UTF-8")) – Dmitry Apr 05 '17 at 23:20
  • Aaaah there it is; the response length is wrong; you are writing in the number of UTF-16 *characters*, but you are sending UTF-8 bytes. I'll update my answer. – Matteo Italia Apr 05 '17 at 23:23
  • thank you! big thank you! спасибо большое:) I got this message in qt client, and I even displayed it in console and in label with correct encoding, everything works perfectly now! – Dmitry Apr 05 '17 at 23:30
  • You're welcome; I'm sorry it took so long, but I didn't notice that you were passing the string size when writing the headers (which is actually quite obvious thinking about how the HTTP response has to be composed). Glad it helped. :-) – Matteo Italia Apr 05 '17 at 23:32