QDataStream unable to serialize data - c++

I am trying to follow the tutorial here and serialize Qt objects. Here is my code:
QFile file("/Users/kaustav/Desktop/boo.dat");
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "Cannot open file for writing: "
<< qPrintable(file.errorString()) << endl; //no error message gets printed
return 0;
}
QDataStream out(&file); // we will serialize the data into the file
out.setVersion(QDataStream::Qt_5_3); //adding this makes no difference
out << QString("the answer is"); // serialize a string
out << (qint32)42;
When I run this program, the file gets created in my desktop all right, but its size is 0 kB, it is blank. Naturally, when I then try this:
QFile file("/Users/kaustav/Desktop/boo.dat");
file.open(QIODevice::ReadOnly);
QDataStream in(&file); // read the data serialized from the file
in.setVersion(QDataStream::Qt_5_3);
QString str;
qint32 w;
in >> str >> w;
I get a blank string in str. What am I doing wrong? If of any help, I am using Qt Creator 3.1.1 based on Qt 5.2.1.

Check if there are any errors returned when calling open and ensure you close the file with file.close() when you're finished with it.
As you're using Qt 5, you should really use QSaveFile instead, when saving the data.

Related

Always empty metadata

I'm writing audio player using QtMutimedia, and need got audio file metadata.
I'm using this code, but always returns empty strings on every file. How fix this?
Qt 5.15.2 MinGw
QStringList meta = player->availableMetaData();
qDebug() << "File meta: ";
foreach(QString data, meta){
qDebug() << data;
}

Is it necessary to flush a QTextStream before closing a QFile?

I need to log some text messages to a file with following requirements :
Each text messages is written in a new line at the end of the file.
Be reasonably sure that each message was correctly written to the file.
So far, the function is using QTextStream and QFile:
bool FileManager::appendLine(const QString &line)
{
if(!m_file.open(QIODevice::Append | QIODevice::Text)) // m_file is a QFile
return false;
QTextStream ts(&m_file);
ts << line << endl;
bool status = (ts.status() == QTextStream::Ok);
m_file.close();
return status;
}
Point 1 is satisfied but i have doubts about Point 2.
Even Qt Doc says that it is sufficient to close() the QFile to flush all its internal buffers :
void QFileDevice::close()
Reimplemented from QIODevice::close().
Calls QFileDevice::flush() and closes the file. Errors from flush are ignored.
What about the internal buffer of the QTextStream ?
Is it necessary to call QTextStream::flush() before closing the file ?
About Point 2, i guess that reading back the line just after it has been written would be the only way to be 100% sure of that. (for example a power failure may occur while the kernel has still datas in its buffers )
Thanks.
In your case, its not, because you are appending &endl in each write!
Writting &endl to the QTextStream writes '\n' to the stream and flushes the stream. It is Equivalent to: stream << '\n' << flush;
Further, when QTextStream is flushed due to &endl, it will empty all data from its write buffer into the device and call flush() on the device.
While this particular code will work because operations with QTextStream end with an endl, it's still better to ensure that QTextStream is completely and utterly finished working with the file when you close it. Just use scopes.
bool FileManager::appendLine(const QString &line)
{
if(!m_file.open(QIODevice::Append | QIODevice::Text)) // m_file is a QFile
return false;
bool status {false};
{
QTextStream ts(&m_file);
ts << line << endl;
status = (ts.status() == QTextStream::Ok);
}
m_file.close();
return status;
}

QT Creator - Parsing through CSV file

OK, so I am using QT Creator for C++ and I am making a function that allows me to parse through the CSV file that I have named getExcelFile. Everything else is working fine but my code will not enter my while loop for some reason which is driving me crazy. Some suggestions would be helpful! Thanks.
void Widget::getExcelFile(){
//Name of the Qfile object.
//filename is the directory of the file once it has been selected in prompt
QFile thefile(filename);
//If the file isn't successfully open
if (thefile.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "File opened successfully";
//Converts text file to stream
QTextStream in(&thefile);
fileContent=in.readAll();
QString line;
while (!in.atEnd()){
//line = textStream.readLine();//reads line from file
//Will not enter this loop for some odd reason.
qDebug() << "This text does not print out";
}
}
qDebug() << "This prints out successfully";
ui->textEdit->setPlainText(fileContent);
}
You did in.readAll(), after that call in.atEnd() will return true. Either remove in.readlAll() or while loop, why do you need both?

Qt Creator combobox

How to write Combobox current text in a preexisting text file in hard drive? Here is my code:
void second::on_pushButton_4_clicked()
{
QFile file("vik.txt");
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;
QTextStream out(&file);
out << ui->comboBox_5->currentText() << "\n";
}
Maybe you forgot to close the file
void second::on_pushButton_4_clicked()
{
// Get comboBox text value
QString txt = ui->comboBox_5->currentText();
// Open file for writing
QFile file("vik.txt");
file.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream out(&file);
// Write in file
out << txt << "\n";
// Close file
file.close();
}
You have several issues in your code, let me enumerate them one-by-one:
You need this flag for "overwrite" as per your comment:
QIODevice::Truncate 0x0008 If possible, the device is truncated before it is opened. All earlier contents of the device are lost.
More importantly, have you checked whether the method returns after open with some error? If it does, please print out file.errorString() there:
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << file.errorString();
return;
}
On the most important note, you are likely facing the issue that the file is not in your current working directory. If the file resides beside the application executable, please change the corresponding line into your code to this:
QFile file(QCoreApplication::applicationDirPath() + "/vik.txt");

Qt getting network requests with QNetworkReply that download data to temp file

I am having some issues reading an online file. I'm trying to read what is in the file after it gets downloaded to a temporary file. Here is my code:
void MainWindow::fileIsReady( QNetworkReply * reply)
{
QTemporaryFile tmpFile;
tmpFile.write(reply->readAll());
QByteArray asdf = reply->readAll();
qDebug() (QString("%1").arg(asdf.length())); // returns 0
if (tmpFile.open())
{
qDebug << "attempting to read file";
QTextStream stream(&tmpFile);
QString value = stream.readAll();
qDebug << value; // value is returning nothing
}
else
{
qDebug() << "failed to open internet file";
}
}
// in MainWindow constructor (MainWindow::MainWindow)...
QNetworkAccessManager * manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileIsReady(QNetworkReply*)) );
manager->get(QNetworkRequest(QUrl("https://www.website.com/stuff/file.exe.md5")));
I'm going to be using this to compare two md5 strings.
There are several issues in your code:
You need to open tmpFile before writing to it.
reply->readAll() will return data only once. Further calls will return empty array. Once you received data using readAll, it's your responsibility to store it in a variable if you need it later.
After you wrote someting to file, the file pointer is at its end. You cannot read anything from it because there is no data there. You can use seek to move pointer to the beginning of the file and read its content.
There is no point in reading from file just after you wrote data to it. You can use QTextStream on QNetworkReply directly to read text from it. (Maybe this was just for debugging, I don't know.)
It's hard to believe that you need to create a temporary file just to calculate md5. There are simplier ways to do that.
So turns out I was dumb and forgot to open the reply first. Also, it was unnecessary for me to create a temp file. Here is my solution::
void MainWindow::fileIsReady( QNetworkReply * reply)
{
if (reply->error() == QNetworkReply::NoError)
{
if (reply->open(QIODevice::ReadOnly))
{
QByteArray asdf = reply->readAll();
qDebug() << (QString("asdf %1").arg(asdf.length()));
qDebug() << (QString(asdf));
}
else
{
qDebug << "cant open reply";
}
}
}