I have a problem with getting diacritic characters from strings encoded in Base64 under QT. I'm creating string then I'm encoding it with Base 64 and I'm saving it to file. Next I want to decode characters from opened file. Here is how I do this.
void MainWindow::on_treeWidget_2_doubleClicked(const QModelIndex &index){
encode("([ęśćźół35:11");
decode();
}
void MainWindow::encode(QString input){
QString item_to_change = input.toUtf8().toBase64();
QString filename="output.txt";
QFile file( filename );
if ( file.open(QIODevice::ReadWrite) )
{
QTextStream stream( &file );
stream << encoded;
}
}
void MainWindow::decode(){
QFile input("output.txt");
if (input.open(QIODevice::ReadOnly)) {
data_in = input.readAll();
}
QString strRestored(QByteArray::fromBase64(data_in));
qDebug() << strRestored;
}
Doing this I'm getting only ([esczol35:11 instead ([ęśćźół35:11
Please help me to get all chars as entered at the beginning.
Thanks
I suspect the problem isn't in the Base64 encoding/decoding because that's going to return exactly what you put in every time; that's the point of it. My belief is that your call to your "encode" method is converting the string literal, or that the toUtf8 is converting it incorrectly. Print out each of those steps using qDebug to see where the problem is, and then you'll probably need to look at the QTextCodec class to set up the conversions properly.
Related
As you can probably tell I am new to QT and I am attempting to import my console app's src code and headers to qt to build a GUI. I am stuck on one particular function which is supposed to load a file and read it in word by word. I know how to do this in C++, but in QT I have been at it for hours and I am not quite sure how to go about it. Along with reading in the file, I have to insert a string (or in this case type T) by using my own personal insert function (irrelevant to the question).
As of right now i am doing which I know is not working for conversion reasons etc:
template <typename T>
bool HashTable<T>::load(const char* filename)
{
QString word;
QFile inputFile(filename);
QTextStream fin(filename);
// std::ifstream iss;
QString line;
// iss.clear();
// iss.open(filename);
while (fin >> word)
{
insert(word);
}
fin.close();
return true;
}
QTextStream does (to my knowledge) not support word-by-word reading of files, it only support reading a certain number of characters (via read(qint64 maxlen)), reading entire lines (via readLine(qint64 maxlen = 0)) or a combination of the above. An example on how to do this is described in this answer.
What you might do - in order to get a list of words - is reading line-by-line, and splitting each read line with QString's split() function, using space as separator.
template <typename T>
bool HashTable<T>::load(const char* filename)
{
QFile inputFile(filename);
if(!inputFile.open(QIODevice::ReadOnly)) {
QMessageBox::information(0, "error", inputFile.errorString());
}
QTextStream fin(&inputFile);
while(!fin.atEnd()) {
QString line = in.readLine();
QStringList words = line.split(" ");
foreach(QString word, words){
insert(word);
}
}
filename.close();
return true;
}
You have to first open your file for reading. Then textstream should be read line by line. In above code I read a line and then split it to words using space (" ") as the token. Then you can read words from the QStringlist.
I've replicated this in two places in my code, one written by me and the one I'm posting an image of, that was written by someone else. I can't get the base64 to output to qDebug at all. I thought base64 was supposed to be readable. It has a size. But it won't print the entire qDebug line.
Thanks in advance for any help.
Here's the code. I'm on Qt Kit 5.12.1 64 bit mingw in release.
QFile* file = new QFile("C:\\Qr-Pic\\Poll_Directory\\IMG_00000001 - Copy (53).jpg");
file->open(QIODevice::ReadOnly);
QByteArray image = file->readAll();
int originalSize = image.length();
QString encoded = QString(image.toBase64());
int encodedSize = encoded.size();
qDebug() << "encodedSize=" << encodedSize;
qDebug() << "encode=" << encoded;
Output:
encodedSize= 34036
I need to load a txt file with 5 millions data (i.e. strings, just one word with 9 characters per word separated by new line.) into QVector as fast as possible. The code is now working just fine however, if the user hits upload, the application takes 3-5 seconds to load this data for further manipulation. I need to decrease the time of loading this data. What is the right approach to handle this issue? I'm Ok with Qt/STL/Boost. I prefer Qt though. The code that I'm using for this task is the one suggested in Qt documentation which is
QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
process_line(line);
}
Try this:
I tested it and read file in 2.1 seconds.
I reserve vector before reading and use QElapsedTimer to get reading time.
void MainWindow::readDataText()
{
QString filePath = "F:\\Qt\\Big_File\\Big_File\\data.txt";
QVector<qint64> *vector = new QVector<qint64>;
vector->reserve(5000000);
QElapsedTimer timer;
QFile readFile(filePath);
if(!readFile.open(QFile::ReadOnly | QFile::Text))
{
// Can't Open File.
}
else
{
QByteArray data;
timer.start();
for (int var = 0; var < 5000000; ++var)
{
vector->insert(var, (readFile.readLine()).toInt());
}
qint64 time = timer.elapsed();
ui->txtReadTimeText->setText(QString::number(time));
}
readFile.close();
}
Also it will better if your file being binary.
Another solution is to use readAll() function and read file in 116 miliseconds, and process(split by '\n') data later like this:
void MainWindow::readDataText()
{
QString filePath = "D:\\ProjectTest\\ProjectTest\\data.txt";
QByteArray data;
data.reserve(5000000);
QElapsedTimer timer;
QFile readFile(filePath);
if(!readFile.open(QFile::ReadOnly | QFile::Text))
{
// Can't Open File.
}
else
{
timer.start();
data = readFile.readAll();
qint64 time = timer.elapsed();
ui->txtReadTimeText->setText(QString::number(time));
}
readFile.close();
}
Your example code actually implicitly does decoding. It reads 8-bit encoded text from the file, and converts it to QString, which internally uses 16 bit Unicode encoding.
You will probably gain a big speedup, if instead of using QTextStream, you use just plain QFile directly, and read form it using this readLine method, which return QByteArray, in other words "raw" file contents. The purpose of doing it this way is to avoid creating QString objects for entire file contents.
If you have 5 million lines, then you will also get a significant memory footprint savings, if you store them in memory in QByteArray, instead of QString. Convert to QString only when you are actually going to display the text in the GUI.
Note: Be aware of text encoding! Any text in any file is always encoded, even if especially English-speakers might not realize it. The most straightforward encoding is 7-bit ASCII, a lot of pure English text is actually this, and almost every encoding including UTF-8 is actually superset of 7-bit ASCII, so 7-bit ASCII file can be loaded using almost any encoding. But for multilingual text, you need to know what encoding the file uses, or you will get the accented and other special characters, like ÄÅÁÀÃ, wrong. UTF8 is the only encoding which can store "everything", other encodings such as Latin1 are designed for specific language families.
Note 2: QByteArray actually corresponds to std::string for most purposes. QString is more like std::wstring. Not saying these are identical 1:1 matches, but it helps to think of them as similar.
I'm a beginner, made a function which takes input from lineedit converts it into a array and then searches it to find a word. If the word is found it prints successs in a label, otherwise prints error.Problem is that it every time prints error no matter what i enter.
What am I doing wrong.
void MainWindow::on_consoleEdit_returnPressed()
{
QString text = ui->consoleEdit->text();
char enteredCmd[4096];
strcpy(enteredCmd, "Some string data");
text = enteredCmd;
//enteredCmd contains all the data that text string contains
char *open = strstr(enteredCmd, "open");
if(open != NULL) {
ui->answerLabel->setText("SUCCESS");
}
else {
ui->answerLabel->setText("ERROR");
}
}
You are testing same string every time, see this:
char enteredCmd[4096];
strcpy(enteredCmd, "Some string data");
text = enteredCmd;
this overrides text value with copy of this "Some string data" string.
Anyway you made this to complicated. QString have lots of functionality useful for you.
void MainWindow::on_consoleEdit_returnPressed()
{
QString text = ui->consoleEdit->text();
if(text.contains("open")) {
ui->answerLabel->setText("SUCCESS");
} else {
ui->answerLabel->setText("ERROR");
}
}
Your code is not searching on the text from the line edit. Your code is actually searching for "open" on the string enteredCmd, which always contains "Some string data". Thus, you should always get "ERROR" printed to your answer label.
Here's what I think you are trying to do, using QString instead of strstr:
void MainWindow::on_consoleEdit_returnPressed()
{
QString text = ui->consoleEdit->text();
if(text.contains(QStringLiteral("open"))) {
ui->answerLabel->setText("SUCCESS");
}
else {
ui->answerLabel->setText("ERROR");
}
}
QString is designed to work with many languages so it requires some conversion to get text to a C style eight bit string. You might try something like this:
char *myChar = text.toLatin1().data();
I need to find and replace some text in the text file. I've googled and found out that easiest way is to read all data from file to QStringList, find and replace exact line with text and then write all data back to my file. Is it the shortest way? Can you provide some example, please.
UPD1 my solution is:
QString autorun;
QStringList listAuto;
QFile fileAutorun("./autorun.sh");
if(fileAutorun.open(QFile::ReadWrite |QFile::Text))
{
while(!fileAutorun.atEnd())
{
autorun += fileAutorun.readLine();
}
listAuto = autorun.split("\n");
int indexAPP = listAuto.indexOf(QRegExp("*APPLICATION*",Qt::CaseSensitive,QRegExp::Wildcard)); //searching for string with *APPLICATION* wildcard
listAuto[indexAPP] = *(app); //replacing string on QString* app
autorun = "";
autorun = listAuto.join("\n"); // from QStringList to QString
fileAutorun.seek(0);
QTextStream out(&fileAutorun);
out << autorun; //writing to the same file
fileAutorun.close();
}
else
{
qDebug() << "cannot read the file!";
}
If the required change, for example is to replace the 'ou' with the american 'o' such that
"colour behaviour flavour neighbour" becomes "color behavior flavor neighbor", you could do something like this: -
QByteArray fileData;
QFile file(fileName);
file.open(stderr, QIODevice::ReadWrite); // open for read and write
fileData = file.readAll(); // read all the data into the byte array
QString text(fileData); // add to text string for easy string replace
text.replace(QString("ou"), QString("o")); // replace text in string
file.seek(0); // go to the beginning of the file
file.write(text.toUtf8()); // write the new text back to the file
file.close(); // close the file handle.
I haven't compiled this, so there may be errors in the code, but it gives you the outline and general idea of what you can do.
To complete the accepted answer, here is a tested code. It is needed to use QByteArray instead of QString.
QFile file(fileName);
file.open(QIODevice::ReadWrite);
QByteArray text = file.readAll();
text.replace(QByteArray("ou"), QByteArray("o"));
file.seek(0);
file.write(text);
file.close();
I've being used regexp with batch-file and sed.exe (from gnuWin32, http://gnuwin32.sourceforge.net/). Its good enough for replace one-single text.
btw, there is not a simple regexp syntax there. let me know If you want to get some example of script.