Comparison in text file using Qt - qt

I am beginner in UI design using Qt. My project now is doing comparison. For example: if I have 2 text file.
How can I compare the number line by line? Because I have so many text file like this, and I need compare them on by one.What I can do now is only read the text file by line order. Thank you so much!

The procedure is simple
Read both files (always make sure they are opened successfully)
Read files line by line and convert strings to numbers for comparison.
Quit if there is no data left.
Moreover, you need to make sure that the format of files is consistent otherwise, you need to make sure what you manipulate is a real number. I assume numbers are integers but of course you can change it. Extra precautions are required in this kind of project. I will leave it to you. The simplified code for the above procedure is
#include <QString>
#include <QFile>
#include <QDebug>
#include <QTextStream>
int main()
{
QFile data1("text1.txt");
if (!data1.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "text1.txt file can't be opened...";
return -1;
}
QFile data2("text2.txt");
if (!data2.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "text2.txt file can't be opened...";
return -1;
}
QTextStream in1(&data1), in2(&data2);
while ( !in1.atEnd() && !in2.atEnd() ) {
QString num1 = in1.readLine();
QString num2 = in2.readLine();
if ( num1.toInt() > num2.toInt() )
qDebug() << num1.toInt() << ">" << num2.toInt();
// do the rest of comparison
}
return 0;
}
Now in my case, the txt files are
text1.txt
1
2
3
4
text2.txt
3
5
1
6
The output is
3 > 1
Edit: the OP is looking for the difference and its sum.
int sum(0);
while ( !in1.atEnd() && !in2.atEnd() ) {
QString num1 = in1.readLine();
QString num2 = in2.readLine();
int result = num1.toInt() - num2.toInt();
qDebug() << num1.toInt() << "-" << num2.toInt() << " = " << result;
sum += result;
}
qDebug() << "sum = " << sum;

Basic approach would be something like this:
QString filename1("C:/Users/UserName/Downloads/t1.txt");
QString filename2("C:/Users/UserName/Downloads/t2.txt");
QFile file(filename1);
file.open(QIODevice::ReadOnly);
QTextStream in(&file);
QStringList textOfFile1;
while (!in.atEnd()) {
QString line = in.readLine();
textOfFile1.append(line);
}
QFile file2(filename2);
file2.open(QIODevice::ReadOnly);
QTextStream in2(&file2);
QStringList textOfFile2;
while (!in.atEnd()) {
QString line = in.readLine();
textOfFile2.append(line);
}
if(textOfFile1.size() != textOfFile2) return false;
for(int i = 0; i < textOfFile1.size(); i++)
{
if(textOfFile1[i] != textOfFile2[i]) return false;
}
return true;
i.e. You read the files into a QStringList and you compare the lists line by line. This way you can also catch the firs # of line where there was a mismatch. Note that such comparison also considers white spaces such as \n \t etc.
PS: wrap the readers into functions, to avoid duplication like me. :)
Hope this helps ;)

Related

Reading from character device with Qt

I'm not very good at character devices, so I need your help. A have a char device(let's call it /dev/my_light) which is a light sensor. I have to read the data from this file and transform it to the brightness value and then pass it to the brightness manager that changes the brightness of my screen. The problem is that when I read the value for some period of time I get old values from the file.I assume there is a buffer(again not sure how character devices exactly work). Whereas when I use cat /dev/my_light I see new data! Is it possible to get rid off the buffer and read new values that were written to the file just right now. Here is my code in Qt:
void MySensor::updateMySensor()
{
Packet packet;
packet.startByte = 0;
packet.mantissa = 0;
packet.exp = 0;
d->device = ::open(d->path.toStdString().c_str(), O_RDONLY);
if (d->device == -1)
{
qDebug() << Q_FUNC_INFO << "can't open the sensor";
return;
}
ssize_t size = ::read(d->device, &packet, sizeof(packet));
close(d->device);
if (size == -1)
{
qDebug() << errno;
return;
}
packet.exp &= 0x0F;
float illumination = pow(2, packet.exp) * packet.mantissa * 0.045;
if(d->singleShot) emit lightSensorIsRunning(true);
emit illuminationRead(illumination);
}
The mySensor function is called every second. I tried to call it each 200 msec but it didn't help. The value of illumination stays old for about 7 seconds(!) whereas the value that I get from cat is new just immediately.
Thank you in advance!
I can't test with your specific device, however, I'm using the keyboard as a read only device.
The program attempts to connect to keyboard and read all keys pressed inside and outside the window. It's a broad solution you'll have to adapt to meet your demands.
Note that I'm opening the file with O_RDONLY | O_NONBLOCK which means open in read only mode and no wait for the event be triggered(some notifier needed to know when data is ready!) respectively.
You'll need super user privilege to run this example!
#include <QtCore>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const char *device_name = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
int descriptor = open(device_name, O_RDONLY | O_NONBLOCK);
if (descriptor < 0)
{
qDebug() << "Error" << strerror(errno);
return a.exec();
}
QFile device;
if (!device.open(descriptor, QFile::ReadOnly))
{
qDebug() << "Error" << qPrintable(device.errorString());
return a.exec();
}
QSocketNotifier notifier(device.handle(), QSocketNotifier::Read);
QObject::connect(&notifier, &QSocketNotifier::activated, &notifier, [&](int socket){
Q_UNUSED(socket)
struct input_event ev;
QByteArray data = device.readAll();
qDebug() << "Event caught:"
<< "\n\nDATA SIZE" << data.size()
<< "\nSTRUCT COUNT" << data.size() / int(sizeof(input_event))
<< "\nSTRUCT SIZE" << sizeof(input_event);
qDebug() << ""; //New line
while (data.size() >= int(sizeof(input_event)))
{
memcpy(&ev, data.data(), sizeof(input_event));
data.remove(0, int(sizeof(input_event)));
qDebug() << "TYPE" << ev.type << "CODE" << ev.code << "VALUE" << ev.value << "TIME" << ev.time.tv_sec;
}
qDebug() << ""; //New line
});
return a.exec();
}

Why does QSettings not store anything?

I want to use QSettings to save my window's dimensions so I came up with these two functions to save & load the settings:
void MainWindow::loadSettings()
{
settings = new QSettings("Nothing","KTerminal");
int MainWidth = settings->value("MainWidth").toInt();
int MainHeight = settings->value("MainHeight").toInt();
std::cout << "loadSettings " << MainWidth << "x" << MainHeight << std::endl;
std::cout << "file: " << settings->fileName().toLatin1().data() << std::endl;
if (MainWidth && MainHeight)
this->resize(MainWidth,MainHeight);
else
this->resize(1300, 840);
}
void MainWindow::saveSettings()
{
int MainHeight = this->size().height();
int MainWidth = this->size().width();
std::cout << "file: " << settings->fileName().toLatin1().data() << std::endl;
std::cout << "saveSettings " << MainWidth << "x" << MainHeight << std::endl;
settings->setValue("MainHeight",MainHeight);
settings->setValue("MainWidth",MainWidth);
}
Now, I can see the demensions being extracted in saveSettings as expected but no file gets created and hence loadSettings will always load 0 only. Why is this?
QSettings isn't normally instantiated on the heap. To achieve the desired effect that you are looking for, follow the Application Example and how it is shown in the QSettings documentation.
void MainWindow::readSettings()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
if (geometry.isEmpty()) {
const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
resize(availableGeometry.width() / 3, availableGeometry.height() / 2);
move((availableGeometry.width() - width()) / 2,
(availableGeometry.height() - height()) / 2);
} else {
restoreGeometry(geometry);
}
}
void MainWindow::writeSettings()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
settings.setValue("geometry", saveGeometry());
}
Also note the use of saveGeometry() and restoreGeometry(). Other similarly useful functions for QWidget based GUIs are saveState() and restoreState() (not shown in the above example).
I strongly recommend the zero parameter constructor of QSettings, and to setup the defaults in your main.cpp, like so:
QSettings::setDefaultFormat(QSettings::IniFormat); // personal preference
qApp->setOrganizationName("Moose Soft");
qApp->setApplicationName("Facturo-Pro");
Then when you want to use QSettings in any part of your application, you simply do:
QSettings settings;
settings.setValue("Category/name", value);
// or
QString name_str = settings.value("Category/name", default_value).toString();
QSettings in general is highly optimized, and works really well.
Hope that helps.
Some other places where I've talked up usage of QSettings:
Using QSettings in a global static class
https://stackoverflow.com/a/14365937/999943

Why is QString printed with quotation marks?

So when you use qDebug() to print a QString, quotation marks appears suddenly in the output.
int main()
{
QString str = "hello world"; //Classic
qDebug() << str; //Output: "hello world"
//Expected Ouput: hello world
}
I know we can solve this with qPrintable(const QString), but I was just wondering why does QString work like that?, and Is there a method inside QString to change the way it's printed?
Qt 5.4 has a new feature that lets you disable this. To quote the documentation:
QDebug & QDebug::​noquote()
Disables automatic insertion of quotation characters around QChar, QString and QByteArray contents and returns a reference to the
stream.
This function was introduced in Qt 5.4.
See also quote() and maybeQuote().
(Emphasis mine.)
Here's an example of how you'd use this feature:
QDebug debug = qDebug();
debug << QString("This string is quoted") << endl;
debug.noquote();
debug << QString("This string is not") << endl;
Another option is to use QTextStream with stdout. There's an example of this in the documentation:
QTextStream out(stdout);
out << "Qt rocks!" << endl;
Why?
It's because of the implementation of qDebug().
From the source code:
inline QDebug &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); }
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromAscii(t); return maybeSpace(); }
inline QDebug &operator<<(const QString & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
Therefore,
QChar a = 'H';
char b = 'H';
QString c = "Hello";
qDebug()<<a;
qDebug()<<b;
qDebug()<<c;
outputs
'H'
H
"Hello"
Comment
So why Qt do this? Since qDebug is for the purpose of debugging, the inputs of various kinds of type will become text stream output through qDebug.
For example, qDebug print boolean value into text expression true / false:
inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
It outputs true or false to your terminal. Therefore, if you had a QString which store true, you need a quote mark " to specify the type.
Qt 4: If the string contains just ASCII, the following workaround helps:
qDebug() << QString("TEST").toLatin1().data();
Simply cast to const char *
qDebug() << (const char *)yourQString.toStdString().c_str();
one liner no quotes: qDebug().noquote() << QString("string");

Qt - Writing a file with QTextStream adds empty new lines to the text

I'm using the following code to write some text to a file:
QFile caFile(outputFolder + "file.extension");
caFile.open(QIODevice::WriteOnly | QIODevice::Text);
if(!caFile.isOpen()){
qDebug() << "- Error, unable to open" << "outputFilename" << "for output";
}
QTextStream outStream(&caFile);
outStream << "First Line\nSecond Line\nThird Line";
caFile.close();
It's working like a charm, but with a little problem ..
The text file should look like this:
First Line
Second Line
Third Line
But instead, it looks like this:
First Line
Second Line
Third Line
What's the problem here?
It works for me like a charm.
input.txt
DA3MTkyMjE0NDdaFw0xODA2MDYyMjE0NDdaMDcxEzARBgNVBAMMCnVqY2E2bjku
anAxEzARBgNVBAoMCnZtamMgMm5vYjMxCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz0+a0BEJEkPwNq7BEplV81+++wzonVAWWcqe
main.cpp
#include <QTextStream>
#include <QFile>
#include <QDebug>
#include <QByteArray>
int main()
{
QFile inFile("input.txt");
inFile.open(QIODevice::ReadOnly | QIODevice::Text);
QByteArray inputData = inFile.readAll();
QFile caFile("output.txt");
caFile.open(QIODevice::WriteOnly | QIODevice::Text);
if(!caFile.isOpen()){
qDebug() << "- Error, unable to open" << "outputFilename" << "for output";
}
QTextStream outStream(&caFile);
outStream << inputData;
caFile.close();
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
Build and Run
qmake && make && ./main
output.txt
DA3MTkyMjE0NDdaFw0xODA2MDYyMjE0NDdaMDcxEzARBgNVBAMMCnVqY2E2bjku
anAxEzARBgNVBAoMCnZtamMgMm5vYjMxCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz0+a0BEJEkPwNq7BEplV81+++wzonVAWWcqe
QString filename = "";//file adding path
QFile file(filename);
file.open(QIODevice::ReadWrite);
QTextStream stream(&file);
stream << "abc\nxyz" << endl;
file.close();
output:abc
xyz

QFile doesn’t create the file

I am writing a simple program. The program has 2 QStrings set with following variables: path and name of file, there is a 3rd QString which I later on use to put the result of the append of the first 2 QString together in. What I want to do is append the 2 QStrings and put them in the appendAll QString, and then send the appendAll QString to the QFile variable constructor. Now when I do that, it prints "Failed to Create File", this is the code I used:
#include <QString>
#include <QTextStream>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextStream output(stdout);
QString location = "/home/mahmoud/Destkop";
QString name = "mahmoud.txt";
QString appendAll;
if( !location.endsWith("/") )
{
location.append("/");
}
appendAll = location.append(name);
output << appendAll << endl;
QFile myFile(appendAll);
if(myFile.open(QIODevice::WriteOnly | QIODevice::Text ))
{
output << "File Has Been Created" << endl;
}
else
{
output << "Failed to Create File" << endl;
}
QTextStream writeToFile(&myFile);
writeToFile << "Hello World" << endl;
myFile.close();
return a.exec();
}
But when I type the string directly into the QFile variable constructor in the same program it prints, "File Has Been Created" and I find it on my desktop, the below code works fine:
QFile myFile("/home/mahmoud/Desktop/mahmoud.txt");
if(myFile.open(QIODevice::WriteOnly | QIODevice::Text ))
{
output << "File Has Been Created" << endl;
}
else
{
output << "Failed to Create File" << endl;
}
I want to be able to already have QStrings and append them and send them to the QFile variable constructor, any suggestions on how to solve my problem? Thank You
Do not hard-code this filesystem location. Instead, in Qt4 you should be using QDesktopServices:
QString location =
QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
In Qt5, it's QStandardPaths:
QString location =
QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
This is important because /home/username/Desktop is not guaranteed to be the user's Desktop folder.
There is typing error in your code: Destkop should be Desktop. Qt can't create file in non-existent directory.

Resources