QByteArray to QString - c++

I'm having issues with QByteArray and QString.
I'm reading a file and stores its information in a QByteArray. The file is in unicode, so it contains something like: t\0 e\0 s\0 t\0 \0 \0
I'm trying to compare this value to my specified value, but it fails, because in the debugger I see it's not an unicode string.
The code will explain everything:
QByteArray Data; //contains unicode string "t\0 e\0 s\0 t\0 \0 \0"
QString myValue = "test"; //value to compare.
if(Data.contains(myValue))
//do some stuff.
else
//do other stuff.
In the debugger, it shows me that the variable Data has the value "t\0 e\0 s\0 t\0 \0 \0" and myValue has the value "test". How can I fix it?

You can use this QString constructor for conversion from QByteArray to QString:
QString(const QByteArray &ba)
QByteArray data;
QString DataAsString = QString(data);

You can use QTextCodec to convert the bytearray to a string:
QString DataAsString = QTextCodec::codecForMib(1015)->toUnicode(Data);
(1015 is UTF-16, 1014 UTF-16LE, 1013 UTF-16BE, 106 UTF-8)
From your example we can see that the string "test" is encoded as "t\0 e\0 s\0 t\0 \0 \0" in your encoding, i.e. every ascii character is followed by a \0-byte, or resp. every ascii character is encoded as 2 bytes. The only unicode encoding in which ascii letters are encoded in this way, are UTF-16 or UCS-2 (which is a restricted version of UTF-16), so in your case the 1015 mib is needed (assuming your local endianess is the same as the input endianess).

You can use:
QString::fromStdString(byteArray.toStdString())

you can use QString::fromAscii()
QByteArray data = entity->getData();
QString s_data = QString::fromAscii(data.data());
with data() returning a char*
for QT5, you should use fromCString() instead, as fromAscii() is deprecated, see https://bugreports.qt-project.org/browse/QTBUG-21872 https://bugreports.qt.io/browse/QTBUG-21872

You may find QString::fromUtf8() also useful.
For QByteArray input of "\010" and "\000",
QString::fromLocal8Bit(input, 1) returns "\010" and ""
QString::fromUtf8(input, 1) correctly returns "\010" and "\000".

Use QString::fromUtf16((ushort *)Data.data()), as shown in the following code example:
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// QByteArray to QString
// =====================
const char c_test[10] = {'t', '\0', 'e', '\0', 's', '\0', 't', '\0', '\0', '\0'};
QByteArray qba_test(QByteArray::fromRawData(c_test, 10));
qDebug().nospace().noquote() << "qba_test[" << qba_test << "]"; // Should see: qba_test[t
QString qstr_test = QString::fromUtf16((ushort *)qba_test.data());
qDebug().nospace().noquote() << "qstr_test[" << qstr_test << "]"; // Should see: qstr_test[test]
return a.exec();
}
This is an alternative solution to the one using QTextCodec. The code has been tested using Qt 5.4.

Qt 5.12 and up:
QString::fromStdString(byteArray.toStdString());

Related

error: no viable conversion from 'std::__1::basic_string<char>' to 'const QString' [duplicate]

What is the most basic way to do it?
If compiled with STL compatibility, QString has a static method to convert a std::string to a QString:
std::string str = "abc";
QString qstr = QString::fromStdString(str);
If by string you mean std::string you can do it with this method:
QString QString::fromStdString(const std::string & str)
std::string str = "Hello world";
QString qstr = QString::fromStdString(str);
If by string you mean Ascii encoded const char * then you can use this method:
QString QString::fromAscii(const char * str, int size = -1)
const char* str = "Hello world";
QString qstr = QString::fromAscii(str);
If you have const char * encoded with system encoding that can be read with QTextCodec::codecForLocale() then you should use this method:
QString QString::fromLocal8Bit(const char * str, int size = -1)
const char* str = "zażółć gęślą jaźń"; // latin2 source file and system encoding
QString qstr = QString::fromLocal8Bit(str);
If you have const char * that's UTF8 encoded then you'll need to use this method:
QString QString::fromUtf8(const char * str, int size = -1)
const char* str = read_raw("hello.txt"); // assuming hello.txt is UTF8 encoded, and read_raw() reads bytes from file into memory and returns pointer to the first byte as const char*
QString qstr = QString::fromUtf8(str);
There's also method for const ushort * containing UTF16 encoded string:
QString QString::fromUtf16(const ushort * unicode, int size = -1)
const ushort* str = read_raw("hello.txt"); // assuming hello.txt is UTF16 encoded, and read_raw() reads bytes from file into memory and returns pointer to the first byte as const ushort*
QString qstr = QString::fromUtf16(str);
Alternative way:
std::string s = "This is an STL string";
QString qs = QString::fromAscii(s.data(), s.size());
This has the advantage of not using .c_str() which might cause the std::string to copy itself in case there is no place to add the '\0' at the end.
std::string s = "Sambuca";
QString q = s.c_str();
Warning: This won't work if the std::string contains \0s.
I came across this question because I had a problem when following the answers, so I post my solution here.
The above examples all show samples with strings containing only ASCII values, in which case everything works fine. However, when dealing with strings in Windows whcih can also contain other characters, like german umlauts, then these solutions don't work
The only code that gives correct results in such cases is
std::string s = "Übernahme";
QString q = QString::fromLocal8Bit(s.c_str());
If you don't have to deal with such strings, then the above answers will work fine.
Do you mean a C string, as in a char* string, or a C++ std::string object?
Either way, you use the same constructor, as documented in the QT reference:
Qt QString Reference
For a regular C string, just use the main constructor:
char name[] = "Stack Overflow";
QString qname(name);
For a std::string, you obtain the char* to the buffer and pass that to the QString constructor:
std::string name2("Stack Overflow");
QString qname2(name2.c_str());
Moreover, to convert whatever you want, you can use the QVariant class.
for example:
std::string str("hello !");
qDebug() << QVariant(str.c_str()).toString();
int test = 10;
double titi = 5.42;
qDebug() << QVariant(test).toString();
qDebug() << QVariant(titi).toString();
qDebug() << QVariant(titi).toInt();
output
"hello !"
"10"
"5.42"
5

Qt C++ QString to QByteArray Conversion

I have created an encrypt/decrypt program, when encrypting I store the encrypted QByteArray in a text file.
When trying to decrypt I retrieved it and then put it into the decryption method, the problem is that I need a way to convert it to QByteArray without changing the format, otherwise it will not decrypt properly. What I mean is if the file gave me an encrypted value of 1234 and I converted that to QByteArray by going 1234.toLatin1() it changes the value and the decryption does not work. Any suggestions?
My Code:
QFile file(filename);
QString encrypted;
QString content;
if (file.open(QIODevice::ReadOnly)) {
QTextStream stream( &file );
content = stream.readAll();
}
encrypted = content.replace("\n", "");
qDebug() << encrypted; // Returns correct encrypted value
QByteArray a;
a += encrypted;
qDebug() << "2 " + a; // Returns different value than previous qDebug()
QByteArray decrypted = crypto.Decrypt(a, key);
return decrypted;
I guess you should use:
QString::fromUtf8(const QByteArray &str)
Or:
QString::QString(const QByteArray &ba)
to convert QByteArray to QString, then write it into file by QTextStream.
After that, read file by QTextStream, use:
QString::toUtf8()
to convert QString to QByteArray.
QString::QString(const QByteArray &ba)
Constructs a string initialized with the byte array ba. The given byte array is converted to Unicode using fromUtf8().
P.S:
Maybe use QFile::write and QFile::read is a better way.
try using toUtf8() .. it works fine with me
If I understand correctly, the text from the file is store in the QString content. I think you could create a new QByteArray. Because the constructor of a QByteArray does not allow a QString as input, I will probably have to append the QString to the empty QByteArray.
//After if:
QByteArray tempContent();
tempContent.append(content);
QByteArray decrypted = crypto.Decrypt(tempContent, key);
I do not have much experience in the Qt library, but I hope this helps.
Or simply go with b64 = data.toUtf8().toBase64();
First convert it to QByteArray with the toUtf8() and then immediately convert it to toBase64()
There's a simple way :
QByteArray ba;
QString qs = "String";
ba += qs;
More hard way:
QByteArray ba;
QDataStream in(&ba, QIODevice::WriteOnly);
in << QString("String");
Extreme way, for people who want to use QBuffer:
#include <QDebug>
#include <QBuffer>
#include <QDataStream>
#include <QIODevice>
#include <QByteArray>
#include <QString>
#include <qcoreapplication.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QByteArray byteArray;
QBuffer buffer(&byteArray);
buffer.open(QIODevice::ReadWrite);
QDataStream in( &buffer );
in << QString("String");
buffer.close();
for (int i = 0; i < byteArray.length(); ++i) {
printf("%c - %x\n", byteArray.at(i), byteArray.at(i));
}
printf("\n");
return a.exec();
}
Who run last code can ask me where does the null byte come from?
QDataStream serializes the QString as a little-endian. 4 bytes are read to create the 32-bit length value, followed by the string itself in UTF-16. This string length in UTF-16 is 12 bytes, so the first three bytes in QByteArray will be zero.
There is often a problem with reading the QByteArray in qDebug () The recording is fine.
Don't forget to remove QT_NO_CAST_FROM_BYTEARRAY in your .pro file, if it has

Displays unwanted character while converting from QDataStream to QChar

I have a code as below
QByteArray bla("abcde");
QDataStream ds(bla.right(bla.size()-1));
QChar c;
ds>>c;
qDebug()<<c; // It prints '?' instead of 'b'
It prints out b if I change the code as
qint8 c;
ds>>c;
qDebug()<<QChar(c); // It now prints 'b'.
It's ok for a single character suppose, I have a lot of characters then I need to make a loop and cast every single of them . Please suggest a good approach.
ds>>c; equals ds>>c.unicode();, which has type ushort &. While QByteArray contains chars.
The correct way to converting QBytaArray to a sequence of QChar would be:
QByteArray bla("abcde");
QTextCodec *codec = QTextCodec::codecForLocale();
const QString string = codec->toUnicode(bla);
foreach (const QChar &c, string) {
qDebug() << c;
}

Convert char * to QString and remove zeros

In my app I read a string field from a file in local (not Unicode) charset.
The field is a 10 bytes, the remainder is filled with zeros if the string < 10 bytes.
char str ="STRING\0\0\0\0"; // that was read from file
QByteArray fieldArr(str,10); // fieldArr now is STRING\000\000\000\000
fieldArr = fieldArr.trimmed() // from some reason array still containts zeros
QTextCodec *textCodec = QTextCodec::codecForLocale();
QString field = textCodec->ToUnicode(fieldArr).trimmed(); // also not removes zeros
So my question - how can I remove trailing zeros from a string?
P.S. I see zeros in "Local and Expressions" window while debuging
I'm going to assume that str is supposed to be char const * instead of char.
Just don't go over QByteArray -- QTextCodec can handle a C string, and it ends with the first null byte:
QString field = textCodec->toUnicode(str).trimmed();
Addendum: Since the string might not be zero-terminated, adding storage for a null byte to the end seems to be impossible, and making a copy to prepare for making a copy seems wasteful, I suggest calculating the length ourselves and using the toUnicode overload that accepts a char pointer and a length.
std::find is good for this, since it returns the ending iterator of the given range if an element is not found in it. This makes special-case handling unnecessary:
QString field = textCodec->toUnicode(str, std::find(str, str + 10, '\0') - str).trimmed();
Does this work for you?
#include <QDebug>
#include <QByteArray>
int main()
{
char str[] = "STRING\0\0\0\0";
auto ba = QByteArray::fromRawData(str, 10);
qDebug() << ba.trimmed(); // does not work
qDebug() << ba.simplified(); // does not work
auto index = ba.indexOf('\0');
if (index != -1)
ba.truncate(index);
qDebug() << ba;
return 0;
}
Using fromRawData() saves an extra copy. Make sure that the str
stays around until you delete the ba.
indexOf() is safe even if you have filled the whole str since
QByteArray knows you only have 10 bytes you can safely access. It
won't touch 11th or later. No buffer overrun.
Once you removed extra \0, it's trivial to convert to a QString.
You can truncate the string after the first \0:
char * str = "STRING\0\0\0\0"; // Assuming that was read from file
QString field(str); // field == "STRING\0\0\0\0"
field.truncate(field.indexOf(QChar::Null)); // field == "STRING" (without '\0' at the end)
I would do it like this:
char* str = "STRING\0\0\0\0";
QByteArray fieldArr;
for(quint32 i = 0; i < 10; i++)
{
if(str[i] != '\0')
{
fieldArr.append(str[i]);
}
}
QString can be constructed from a char array pointer using fromLocal8Bit. The codec is chosen the same way you do manually in your code.
You need to set the length manually to 10 since you say you have no guarantee that an terminating null byte is present.
Then you can use remove() to get rid of all null bytes. Caution: STRI\0\0\0\0NG will also result in STRING but you said that this does not happen.
char *str = "STRING\0\0\0\0"; // that was read from file
QString field = QString::fromLocal8Bit(str, 10);
field.remove(QChar::Null);

How do I see the contents of Qt objects QByteArray during debugging?

My program use some variables of type QByteArray to contain data (bytes). That bytes maybe are special characters like '\0', 1, ... So I cannot see all elements after special character when debugging. If I use std::vector, I can see all elements. I must use QByteArray but I cannot see all element of this variable when debugging. Help me, plz!
Thanks!
Example: QByteArray bytes(4, '\0');
Now, if debug, I just see "". But I want to see "'\0', '\0', '\0', '\0'" or something like like this.
I also have the same problem with QDateTime. But I resolved by this help: http://www.qtcentre.org/threads/32336-View-QDate-and-QDateTime-in-VisualStudio-debugger
This link may help but this not resolve my problem: http://qt-project.org/wiki/IDE-debug-helpers
Example:
QByteArray ba("Hello"); //debuging, see: ba = "Hello"
ba.append('\0');
ba.append("a message"); //we just see: ba = "Hello"
I contribute here a piece of code I had to write since I could not find any method doing something close to that: display a QByteArray as a meaningful QString in a way python would do it: ascii is kept as this, special char are displayed as hexadecimal code.
If someone knows a better way ! (here it's QT 4.6)
QString toDebug(const QByteArray & line) {
QString s;
uchar c;
for ( int i=0 ; i < line.size() ; i++ ){
c = line[i];
if ( c >= 0x20 and c <= 126 ) {
s.append(c);
} else {
s.append(QString("<%1>").arg(c, 2, 16, QChar('0')));
}
}
return s;
}
Such as:
QByteArray a;
a.append("et");
a.append('\0');
a.append("voilà");
qDebug() << toDebug(QByteArray(a));
returns:
"et<00>voil<e0>"
For debugging, you can convert QBytearray to QString and see the output.
For example:
QByteArray bArray;
QString str = "";
str.append(bArray);
QDebug() << str ; // this will display the content in your console/application output window
hope this will resolve your issue.