Qt5: How to read/write the file in local file system - c++

I'm new to Qt.In my app,I want to press a button and it will come out a QFileDialog to let me select the file in file system .So how to do that?
After that , here is my problem, I don't know which API in Qt works just like "open" in POSIX ? I think if I can open the file in the right way , this API will return me a file descriptor and I can read/write this file like open did in posix.
I read some documents and found some classes such as QFile QDataStream but I don't know if they are exactly what I want.

Those are exactly what you are looking for.
In particular, you can use some of the static methods of QFileDialog to get a reference to the file you want to open, like:
static QString getOpenFileName(QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, Options options = 0)
and then use a QFile and QDataStream or QTextStream to read the contents.
You'd use QDataStream for reading binary data most of the times, like follows:
QFile f(fileName);
if (f.open(QIODevice::ReadOnly)) {
QDataStream stream(&f);
int data;
stream >> data;
}
Otherwise you can read plain text with QTextStream as follows:
QTextStream stream(&f);
QString line;
do {
line = stream.readLine();
/* do something with the line */
} while (!line.isNull());
Qt docs are pretty complete, you just have to take your time and read them. There's also plenty of examples.

Only Reading:
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open file"), "", tr("all Files ()"));
QFile file(fileName);
if(file.open(QIODevice::ReadOnly)){
QByteArray arr = file.readAll();
file.close();
}
Only Writing:
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open file"), "", tr("all Files ()"));
QFile file(fileName);
if(file.open(QIODevice::WriteOnly)){
file.write(QBtyeArray("Heelo World"));
file.close();
}
Read and Write:
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open file"), "", tr("all Files ()"));
QFile file(fileName);
if(file.open(QIODevice::ReadWrite)){
QByteArray arr = file.readAll();
arr += " From Earth";
file.write(arr);
file.close();
}
if you use QDatastream you do not need resolve how many part you have written before,follow Below Code and I always use this method;
QBuffer buffer;
buffer.open(QIODevice::WriteOnly);
QDatastream out(&buffer);
out << QString("Hello World QString");
out << QByteArray("Hello World QByteArray");
out << int(55);
buffer.close();
QFile file(fileName);
if(file.open(QIIDevice::WriteOnly)){
file.write(buffer.data());
file.close();
}
and reading this file
QFile file(fileName);
if(file.open(QIIDevice::WriteOnly)){
QDatastream in(&file);
QString str;
QByteArray arr;
int integer;
in >> str;
in >> arr;
in >> integer;
file.close();
}
str is "Hello World QString";
arr is "Hello World QByteArray";
integer is 55;
QDataStream is adding extra bytes to file for your parts and if you read it with QDataStream, QDataStream solve how many parts and each part bytes instead of you.

Related

Converting valid QFile to QString - QString is empty

So I am trying to convert a QFile into a QString by doing the following:
void MainWindow::openTemplateFile(QString location)
{
if (location.isEmpty())
return;
else
{
QString variable;
templateFile.setFileName(location);
if (!templateFile.open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::information(this, "Unable to open template",
templateFile.errorString());
return;
}
else // file opened and ready to read from
{
QTextStream in(&templateFile);
QString fileText = in.readAll();
qDebug() << templateFile.size() << in.readAll();
}
}
}
However, in I get the following result in the debug console:
48 ""
templateFile does exist and is part of the MainWindow class. This is also simplified code - in the actual program I read chars from the file and it works correctly. The location string is a result of the QFileDialog::getOpenFileName function, which I open a txt file with.
You call readAll() twice. The second time, the stream is positioned at end-of-file, and so readAll() has nothing to read and returns an empty string. Print fileText in your debug output instead.

How to recursively write data to a text file in C++/ Qt

I have a C++\Qt program that scans the files in a particular directory. I'm trying to write the paths to the files contained therein in a text file, but all I've managed to do is write the path to the last file.
void ScanDir::qDirIteratorScanner(QString path)
{
QDirIterator it(path, QStringList() << "*.mp4", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext())
{
WriteToFile writeToFile(path, it.next());
qDebug() << "it.next()";
}
}
...
WriteToFile::WriteToFile(QString path, QString data)
{
path += "/Data.txt";
QFile file(path);
if (file.open(QFile::ReadWrite)) {
QTextStream stream(&file);
stream << data << endl;
}
}
How can I write all the paths into the text file?
You're creating a QFile in read/write mode at each call of WriteToFile: this is truncating the contents of the file, so only contents written by the last call will remain.
Try:
void ScanDir::qDirIteratorScanner(QString path)
{
QDir dir(path);
QFile file(dir.absoluteFilePath("Data.txt"));
if (file.open(QFile::ReadWrite)) {
QTextStream stream(&file);
QDirIterator it(
dir,
QStringList() << "*.mp4",
QDir::Files,
QDirIterator::Subdirectories
);
while (it.hasNext())
{
stream << it.next() << endl;
}
}
}
Here the file is opened only once. If you want/need to keep a function WriteToFile, pass stream as an additional parameter (by reference).
Note:
As proposed by Simon Kraemer in the comments, I used QDir::absoluteFilePath as it makes it easier to prevent missing or accidental slashes in the path.
An alternative to keep your design may be to use QFile::Append mode:
void ScanDir::qDirIteratorScanner(QString path)
{
QDir dir(path);
// reset the file
{
QFile file(dir.absoluteFilePath("Data.txt"));
file.open(QFile::ReadWrite);
}
QDirIterator it(
dir,
QStringList() << "*.mp4",
QDir::Files,
QDirIterator::Subdirectories
);
while (it.hasNext())
{
WriteToFile writeToFile(path, it.next());
qDebug() << "it.next()";
}
}
WriteToFile::WriteToFile(QString path, QString data)
{
QDir dir(path);
QFile file(dir.absoluteFilePath("Data.txt"));
if (file.open(QFile::Append)) {
QTextStream stream(&file);
stream << data << endl;
}
}
Each time you open the file and write one line to it, overwriting whatever is in the file. Instead, try opening it in append mode, this should cause whatever you write to be added at the end of the file.
QTextStream stream(&file,QIODevice::Append);
You must open the file in "append" mode, otherwise you will override its content every time you open the file:
file.open(QFile::Append)
2 remarks to your code:
Writing to a file from a constructor seems questionable. Why don't you just declare a function?
Why don't you open the file just once?
void ScanDir::qDirIteratorScanner(QString path)
{
QFile file(QDir(path).absoluteFilePath("Data.txt"));
if(file.open(QFile::WriteOnly))
{
QTextStream stream(&file);
QDirIterator it(path, QStringList() << "*.mp4", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext())
{
stream << it.next() << endl;
qDebug() << "it.next()";
}
}
}
It would be most efficient to move the file opening and writing to qDirIteratorScanner() instead of WriteToFile(). This way you can open the file, write everything, then close the file.
What you have now is you keep on opening (and overwriting) the same file on every iteration. That's why you are only left with the last write. Alternatively, you could open the file with the QIODevice::Append flag, but that's just unnecessary operations compared to the first suggestion, where you will open the file only once to write everything.

Can't save PNG image into file

I have some troubles with image saving. I have to crop "1.png" by rect and save it to file, but an empty one is appearing (0 bytes). What am I doing wrong?
void RedactorForm::cropButtonSlot(int x1, int y1, int x2, int y2) {
QImage pixmap("1.png");
QRect rect(x1,y1,x2,y2);
pixmap=pixmap.copy(rect);
QString fileName("D:/yourFile.png");
QFile file(fileName);
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
pixmap.save(fileName,0,100);
out <<pixmap;
}
QImage's save method does not take a file name as a parameter, it taske a QFile. Try this;
pixmap.save(&file, "PNG");
You don't need use QDataStream for this task. Use directly save method of QImage. Your code should be like this:
QImage pixmap("1.png");
...................
QString fileName("D:/yourFile.png");
QFile file(fileName);
if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
pixmap.save(&file, "PNG");
}
else {
qDebug() << "Can't open file: " << fileName;
}
I think you have to close the file which you opened before. Also you don't need to open the file at all. You can do that:
QRect rect(x1,y1,x2,y2);
QImage pixmap(x2-x1,y2-y1,QImage::Format_ARGB32);
pixmap.copy(rect);
QFile file("D:/yourFile.png");
pixmap.save(file.fileName(),"PNG");

Parsing QByteArray

I have a file name into a QByteArray
QString file_name = "icon.jpg";
QByteArray qba1; qba+=file_name;
I have the contents of a file into a QByteArray
QFile file("C:\\Devel\\icon.jpg");
if (file.open(QIODevice::ReadOnly)){
QByteArray content = file.readAll();
}
How to connect the file name and the contents of one variable of type QByteArray?
How to parse this variable QByteArray back to file name and content?
Simplest way is to start with the length of the filename, then the filename itself, followed by the data. Parsing the data back is as simple as reading the filename-length first, read the filename, then the data.
QByteArray qbaFileName((const char*)(file_name.utf16()), file_name.size() * 2);
QByteArray byteArray;
QDataStream stream(&byteArray, QIODevice::WriteOnly);
stream << (int)qbaFileName.size(); // put length of filename on stream
stream << qbaFileName; // put filename on stream
stream << file.readAll(); // put binary data on stream

Opening a file from a Qt String

I am making a Qt application and I have a button to open a file, which is connected to a custom slot. This is the slot code so far:
void MainWindow::file_dialog() {
const QFileDialog *fd;
const QString filename = fd->getOpenFileName();
}
How could I have it then convert the file name to a const char *, open the file, read it and store the text in a QString, and then close the file. I am using Qt4.
To read the contents of a file, you can do this:
QString filename = QFileDialog::getOpenFileName();
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QString content = file.readAll();
file.close();