Comparing QByteArrays - c++

I am making a file editor in Qt C++.
I noticed that when I save the source file with notepad on Windows it substitutes 0x0D + 0x0A for every new line (ANSI encoding default).
If I get the data from a QTextEdit and convert that to a QByteArray it substitutes line endings with 0x0A.
Now my main problem is that I don't know how to either filter out these line endings or make it so that QFile reads files different.
I just want a way of comparing whether there are changes that need to be saved.
The code is below:
bool QFileTab::needSave()
{
QFile file1 ( this->filePath );
file1.open(QIODevice::ReadOnly);
QByteArray data1 ( file1.readAll() );
QByteArray data2 ( this->body.toPlainText().toLocal8Bit() );
file1.close();
return !IOHandler::compare(data1, data2);
}
void IOHandler::read(QFileTab *tab)
{
QFile temp (tab->filePath);
if(temp.open(QIODevice::ReadOnly | QIODevice::Text))
{
QString data(temp.readAll());
tab->data = data;
temp.close();
} else tab->data = QString("The file could not be read.");
tab->doUpdate();
}
bool IOHandler::compare(QByteArray data1, QByteArray data2)
{
return data1 == data2;
}
I want to be able to read, compare and write to files on Windows and Linux.

Related

Better way to use QDomDocument data as text

I am a newbie, I am creating a XML file in which I need to give CRC value to cross check on server. For this I need QDomDocument data as text. For this I am first creating XML file with fake CRC value. Then I open it with QFile and read all data. Then I split data and calculate data CRC. Now I have to rewrite whole file again. I know it is the worst idea ever to write same file twice but as I am a newbie, I don't know how to do it in better style. Here is my code:-
QDomElement docElem = doc.documentElement();
QFile xmlfile(filename);
if(!xmlfile.open(QIODevice::ReadWrite | QIODevice::Text))
{
qDebug("Can not open file device.");
}
xmlfile.resize(0);
QXmlStreamWriter xw;
xw.setDevice(&xmlfile); //set file to XML writer
xw.setAutoFormatting(true);
xw.setAutoFormattingIndent(4);
xw.writeStartDocument();
xw.writeStartElement(fileID); //fileID as the start element
if(docElem.hasAttributes())
{
xw.writeAttribute("xmlns:xs",docElem.attribute("xmlns:xs"));
xw.writeAttribute("xmlns",docElem.attribute("xmlns"));
}
xw.writeTextElement("Frame_Start_ID","STX");
xw.writeTextElement("Frame_Length","1234");
xw.writeTextElement("Source_Device_Id","CDIS_PIS ");
xw.writeTextElement("Destination_Device_Id","DDNS-SERVER ");
xw.writeTextElement("Frame_Code","I");
xw.writeStartElement("Frame_Data");
//inside frame data
xw.writeTextElement("File_Number","1");
xw.writeTextElement("File_Name","Event");
for(int j=0;j<logFields.count();j++)
{
xw.writeTextElement(logFields.at(j),logData.at(j));
}
xw.writeEndElement();
xw.writeTextElement("CRC","14405904");
xw.writeTextElement("Frame_End_Id","ETX");
xw.writeEndDocument();
xmlfile.flush();
xmlfile.close();
QFile xmlfyle(filename);
xmlfyle.open(QIODevice::ReadWrite | QIODevice::Text);
QString content = (QString)xmlfyle.readAll();
QStringList list1 = content.split("<CRC>");
qDebug() << "Split value = " << list1.at(0);
QByteArray crc_new = crc_o.crc_generate_modbus((unsigned char*)list1.at(0).data(),list1.at(0).size());
xmlfyle.resize(0);
QXmlStreamWriter xw_new;
xw_new.setDevice(&xmlfyle); //set file to XML writer
xw_new.setAutoFormatting(true);
xw_new.setAutoFormattingIndent(4);
xw_new.writeStartDocument();
xw_new.writeStartElement(fileID); //fileID as the start element
if(docElem.hasAttributes())
{
xw_new.writeAttribute("xmlns:xs",docElem.attribute("xmlns:xs"));
xw_new.writeAttribute("xmlns",docElem.attribute("xmlns"));
}
xw_new.writeTextElement("Frame_Start_ID","STX");
xw_new.writeTextElement("Frame_Length","1234");
xw_new.writeTextElement("Source_Device_Id","CDIS_PIS ");
xw_new.writeTextElement("Destination_Device_Id","DDNS-SERVER ");
xw_new.writeTextElement("Frame_Code","I");
xw_new.writeStartElement("Frame_Data");
xw_new.writeTextElement("File_Number","1");
xw_new.writeTextElement("File_Name","Event");
for(int j=0;j<logFields.count();j++)
{
xw_new.writeTextElement(logFields.at(j),logData.at(j));
}
xw_new.writeEndElement();
char tab[10];
sprintf(tab,"%d",crc_new.data());
xw_new.writeTextElement("CRC",QString::fromUtf8(tab));
xw_new.writeTextElement("Frame_End_Id","ETX");
xw_new.writeEndDocument();
xmlfyle.flush();
xmlfyle.close();
can anyone suggest me what could be a better way to do this.Thanks
One version of QXmlStreamWriter constructor accepts a QByteArray and writes into the array instead of an output file.
QXmlStreamWriter Class
So what you can do is; using QXmlStreamWriter, prepare data for your XML in a QByteArray, do whatever you need to do with the CRC inside this data; and when everything is done, write this QByteArray to the output file.

QstringList to Qstring conversion issues

I am working on VS2015 with qt framework. In my source code, I have a function for printing in the GUI screen.
This function is called each time something needs to be printed.
It goes like this.
void Trial::Print_MessageBox(QString string)
{
ui.MessagesScreen->appendPlainText(string);
Cursor_Messagebox.movePosition(QTextCursor::End);
ui.MessagesScreen->setTextCursor(Cursor_Messagebox);
ui.MessagesScreen->ensureCursorVisible();
}
// Output in MessageBox
void Trial::Print_MessageBox(QFlags<QNetworkInterface::InterfaceFlag> flags)
{
QString str = QString("Flag %1").arg(flags);
ui.MessagesScreen->appendPlainText(str);
}
The above function has no problems and running well.
Now I am trying to read a text file. This has set of values in no order or size. An example for this:
231, 54, 4 \n
47777, 2211, 676, 9790, 34236, 7898\n
1, 3\n
Objective is to convert these into integers (line by line) and print them in the GUI and also send them (line by line) to other system. So I tried to do it with the following.
void Trial::ReadFile_Data()
{
QFile file("input.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
Print_MessageBox("Error in reading File");
return;
}
QTextStream in(&file);
while (!in.atEnd())
{
QString line = in.readLine();
Print_MessageBox(line);
int conv = line.toInt();
QString str = QString("%1 %2").arg("Values are: ").arg(conv);
Print_MessageBox(str);
QStringList fields = line.split(",");
}
file.close();
}
When I print the "line", it is just printing the same values as in the file. When I do the conversion and printing, I get an error (which is expected) Now I try to remove "," with the help of split then I get QstringList which I cannot use as I have the Qstring function to print(this cant be changed)
I am not getting any pointers from here. Please help me out as this is bugging me since long time.
Just simple...
QStringList::const_iterator constIterator;
for (constIterator = fonts.constBegin(); constIterator != fonts.constEnd();
++constIterator) {
cout << (*constIterator).toLocal8Bit().constData() << endl;
}
where fonts is your QStringlist
Your question reduces to "How do I iterate over a QStringList".
Like this:
// C++11
for (auto field : fields) Print_messageBox(field);
// C++98
foreach (QString field, fields) Print_messageBox(field);
See here for information about how foreach a.k.a Q_FOREACH was implemented.

Qt delete a line from file

I am reading a QFile with QTextStream.
QFile file("example.txt");
QTextStream in(&file);
QString line = in.readLine();
while (!line.isNull()) {
if(line.contains("DELETE"))
{
// delete line
}
line = in.readLine();
}
Is there a way to delete a line ?
You can open your file, read the contents, modify the contents, and then write them back to the file. Here is one way to do this:
QFile f("myfile.txt");
if(f.open(QIODevice::ReadWrite | QIODevice::Text))
{
QString s;
QTextStream t(&f);
while(!t.atEnd())
{
QString line = t.readLine();
if(!line.contains("DELETE"))
s.append(line + "\n");
}
f.resize(0);
t << s;
f.close();
}
As far as i know, it's not simple as that. The best solution i can think about is to the read the whole file line-by-line, push every line into a QVector, then modify the container's elements as you want, then push it back to the file.
delete a line means shift of all the rest backward.
simplest way is to write back lines in new place after first deletion.
Using temp file, and rename it to the original if success, is the safest way.
but you never write more then you read so it suppose to be OK to work on the same file.
you need to keep read pos and write pos.
it should be something like this: (based on the original code)
QFile file("example.txt");
QTextStream in(&file,QIODevice::ReadWrite);
QString line = in.readLine();
qint64 rpos,wpos=0;
bool shift = false;
while (!line.isNull()) {
rpos = in.pos();
if(!line.contains("DELETE"))
{
if(shift){
in.seek(wpos);
in<<line<<endl;
wpos = in.pos();
in.seek(rpos);
} else{
wpos = rpos;
}
}else{
shift = true;
}
in.seek(rpos);
line = in.readLine();
}
file.resize(wpos);

Qt QSerialPort buffering

I am reading information from a serial port. How do I wait for a newline to come in, and then deal with the data? That is, how do I make sure I'm chunking a whole line at a time.
This code does not work:
void MainWindow::readData()
{
QByteArray data = serial->readAll(); //reads in one character at a time (or maybe more)
console->putData(data);
charBuffer.append(data);
if (data.contains("\n")) //read into a structure until newline received.
{
//call parsedata
sensorValues->parseData(charBuffer); //send the data to be parsed.
//empty out the structure
charBuffer = "";
}
}
Let's say the serial port sends "Sensor1 200\n".
data might contain the following: "Se" then "n", "sor 2" "00\n" and so on.
How do I block calling parseData until I have a line of text?
Additional info:
readData is set up as a slot:
connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));
Have you not tried using the SerialPort readLine() function? after each readline(), you can send the line to some new ByteArray or QString to be parsed up. I also use .trimmed() on the end to remove the '\r' and '\n' characters, so I can do something like so:
void MainWindow::readData()
{
while (serial->canReadLine()){
QByteArray data = serial->readLine(); //reads in data line by line, separated by \n or \r characters
parseBytes(data.trimmed()) ;
}
}
void MainWindow::parseBytes(const QByteArray &data) <--which needs to be moved to separate class, but here it's in the MainWindow, obviously improper
{
if (data.contains("1b0:"))
{
channel1Data.b0_code = data.mid(5); // which equals "1",
//do stuff or feed channel1Data.b0_code to a control
}
}
Make a static variable and then store data until you got an \n
void readData()
{
// Read data
static QByteArray byteArray;
byteArray += pSerialPort->readAll();
//we want to read all message not only chunks
if(!QString(byteArray).contains("\n"))
return;
//sanitize data
QString data = QString( byteArray ).remove("\r").remove("\n");
byteArray.clear();
// Print data
qDebug() << "RECV: " << data;
//Now send data to be parsed
}

Qt C++ writing data in a file , unexpected output

I have a task to save a file to computer. So this is my problem, when i write to file , it writes hex values.. I have no clue, what's wrong with my code. Here it is:
void MainWindow::on_actionSave_triggered()
{
QString filename = QFileDialog::getSaveFileName(
this,
tr("Save Document"),
QDir::currentPath(),
tr("Documents (*.txt)") );
QFile f( filename );
f.open( QIODevice::WriteOnly | QIODevice::Text );
QTextStream out(&f);
out << ui->textEdit->document();
}
QTextEdit's document method return QTextDocument, I think you want to use toPlainText method instead.
QTextEdit::document() will return a QTextDocument* which will be an Hex value (address). That's what you are adding in the file.
To get the contents from the QTextEdit use QString QTextEdit::toPlainText ()
HTH..