Modify a .txt file
-
Hi all,
I have a large
.txt
file containing settings to configure a serial device. I can access each lines of the file by doing this:QString filename = "config_keygrip"; QString path = QCoreApplication::applicationDirPath()+"/"+filename+".txt"; QFile file(path); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::information(this, "Unable to open file for read", file.errorString()); return; } else { QTextStream in(&file); while(!in.atEnd()) { QString line = in.readLine(); QString trackName("O CH1"); int pos = line.indexOf(trackName); if (pos >= 0) { ui->textBrowser->setText(line) //--> to see the line } } file.close(); }
In the above case the
QString line
read as:O CH2 0mA 0ms 0ms 600000ns 180us RATE
Here how do I modify this line and write back to the original file?
For example I want to replace number 180 with a different value get through a
QSlider
ui->verticalSlider_ch1->value()
-
Hi all,
I have a large
.txt
file containing settings to configure a serial device. I can access each lines of the file by doing this:QString filename = "config_keygrip"; QString path = QCoreApplication::applicationDirPath()+"/"+filename+".txt"; QFile file(path); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::information(this, "Unable to open file for read", file.errorString()); return; } else { QTextStream in(&file); while(!in.atEnd()) { QString line = in.readLine(); QString trackName("O CH1"); int pos = line.indexOf(trackName); if (pos >= 0) { ui->textBrowser->setText(line) //--> to see the line } } file.close(); }
In the above case the
QString line
read as:O CH2 0mA 0ms 0ms 600000ns 180us RATE
Here how do I modify this line and write back to the original file?
For example I want to replace number 180 with a different value get through a
QSlider
ui->verticalSlider_ch1->value()
@viniltc
This seems to get asked frequently here. Answered as simply as possible, you cannot update lines in a text file in situ, i.e. any kind of "open file for update and insert/remove a bit here". You have to either:- Read whole file into memory, makes changes in memory, overwrite existing file with whole new content.
- Read a line at a time from file, changing as necessary, and writing that out a line at a time to a new, temporary file. On conclusion, delete original file and rename temporary file.
-
Maybe not a clean Way, but you can split the Line and get the Value. Save the Value in a Variable and bind it to your Silder. Make a Save Button. When you save then build a new String and replace the complete Line. When you read the Line maybe you can count the Lines, so you know in which Line you have to replace everything. For that you need the complete File in a String or something. To write everything back is as easy as you read the File. Just overwrite everything.
Thats the first Thing i would try, but perhaps someone has a better Solution.
-
Hi
O CH2 0mA 0ms 0ms 600000ns 180us RATE
Does all line have the same format ? (same positions of values)
Also, do you write out this file your self ? ( so you can control the format)
Also how big is big?
For random editing, in-memory editing is far more fun than ON THE FLY change reading file line by line and
then change a line before writing it back.
However, it really depends on what the actual use case is.
If only need to change one value, one time, it won't matter much :) -
Hi
O CH2 0mA 0ms 0ms 600000ns 180us RATE
Does all line have the same format ? (same positions of values)
Also, do you write out this file your self ? ( so you can control the format)
Also how big is big?
For random editing, in-memory editing is far more fun than ON THE FLY change reading file line by line and
then change a line before writing it back.
However, it really depends on what the actual use case is.
If only need to change one value, one time, it won't matter much :)@JonB , @Fuel-0 @LeLev @mrjj Thanks a lot for your feedback. I'm sorry for my vague explanation.
An incomplete configuration file looks like this:
`R ref, version, "config_ID", menu language, Power timeout (hours), Number of users R R1 1 "Template for setting parameters" ENGLISH 1 1 `U ref, "user name", language, volume, number of activities U U1 "Any user" ENGLISH 100% 1 `A ref, "activity name", max duration, max cycles, startingPW%, available/hidden A A1 "Setup stim levels" 0min 0 0% AVAILABLE FALSE FALSE TRUE TRUE B SA1 1 "Engine tests" ` These limits apply to all phases ` M ref stim, channel, max current, minPW, maxPW, freq, waveform, output name M CH1 1 1 120mA 10us 450us 40Hz ASYM "Channel 1" M CH2 1 2 120mA 10us 450us 40Hz ASYM "Channel 2" P P0 "Test phase" 0ms NONE 2000ms STOP STOP STOP ` Delay RR rate PW O CH1 0mA 0ms 0ms 600000ns 180us RATE O CH2 0mA 0ms 0ms 600000ns 180us RATE
I basically need to change parameters in the last two lines of the file. I can access a particular line but don't know how to split the Line and get the Value. Here parameters are presented as a list of space-separated variables.
p.s.
The description is formatted as ASCII text. Multiple space characters are collapsed into one. Comments are enclosed in``
and replaced with space characters. A single backtick ` starts a comment that continues to the end of the line. -
@JonB , @Fuel-0 @LeLev @mrjj Thanks a lot for your feedback. I'm sorry for my vague explanation.
An incomplete configuration file looks like this:
`R ref, version, "config_ID", menu language, Power timeout (hours), Number of users R R1 1 "Template for setting parameters" ENGLISH 1 1 `U ref, "user name", language, volume, number of activities U U1 "Any user" ENGLISH 100% 1 `A ref, "activity name", max duration, max cycles, startingPW%, available/hidden A A1 "Setup stim levels" 0min 0 0% AVAILABLE FALSE FALSE TRUE TRUE B SA1 1 "Engine tests" ` These limits apply to all phases ` M ref stim, channel, max current, minPW, maxPW, freq, waveform, output name M CH1 1 1 120mA 10us 450us 40Hz ASYM "Channel 1" M CH2 1 2 120mA 10us 450us 40Hz ASYM "Channel 2" P P0 "Test phase" 0ms NONE 2000ms STOP STOP STOP ` Delay RR rate PW O CH1 0mA 0ms 0ms 600000ns 180us RATE O CH2 0mA 0ms 0ms 600000ns 180us RATE
I basically need to change parameters in the last two lines of the file. I can access a particular line but don't know how to split the Line and get the Value. Here parameters are presented as a list of space-separated variables.
p.s.
The description is formatted as ASCII text. Multiple space characters are collapsed into one. Comments are enclosed in``
and replaced with space characters. A single backtick ` starts a comment that continues to the end of the line.@viniltc said in Modify a .txt file:
I can access a particular line but don't know how to split the Line and get the Value.
One of the https://doc.qt.io/qt-5/qstring.html#split overloads. For (multiple) whitespace probably
line.split(QRegularExpression("\\s+"))
. Or spaces only, I think,line.split(' ', QString::SkipEmptyParts)
. If guarantee only one space separator (you say this, but files doesn't look like that),line.split(' ')
.(Of course, if you actually need to parse the file to deal correctly with your backtick comments to find the right line that is another matter.)
-
@JonB Thanks. That works perfectly.
Can someone show me example how to write content back to the file. If I do following change to the line.
QString filename = "config_keygrip"; QString path = QCoreApplication::applicationDirPath()+"/"+filename+".txt"; QFile file(path); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::information(this, "Unable to open file for read", file.errorString()); return; } else { QTextStream in(&file); while(!in.atEnd()) { QString line = in.readLine(); QString trackName("O CH1"); int pos = line.indexOf(trackName); if (pos >= 0) { QStringList list = line.split(' ', QString::SkipEmptyParts); QString currVal = QString::number(ui->verticalSlider->value()); list[3] = currVal; } } file.close(); }
-
@JonB Thanks. That works perfectly.
Can someone show me example how to write content back to the file. If I do following change to the line.
QString filename = "config_keygrip"; QString path = QCoreApplication::applicationDirPath()+"/"+filename+".txt"; QFile file(path); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::information(this, "Unable to open file for read", file.errorString()); return; } else { QTextStream in(&file); while(!in.atEnd()) { QString line = in.readLine(); QString trackName("O CH1"); int pos = line.indexOf(trackName); if (pos >= 0) { QStringList list = line.split(' ', QString::SkipEmptyParts); QString currVal = QString::number(ui->verticalSlider->value()); list[3] = currVal; } } file.close(); }
@viniltc https://doc.qt.io/qt-5/qfile.html has examples how to write into a file. Just iterate over your QStringList and write each entry into the file.
-
Maybe not a clean Way, but you can split the Line and get the Value. Save the Value in a Variable and bind it to your Silder. Make a Save Button. When you save then build a new String and replace the complete Line. When you read the Line maybe you can count the Lines, so you know in which Line you have to replace everything. For that you need the complete File in a String or something. To write everything back is as easy as you read the File. Just overwrite everything.
Thats the first Thing i would try, but perhaps someone has a better Solution.
-
@viniltc https://doc.qt.io/qt-5/qfile.html has examples how to write into a file. Just iterate over your QStringList and write each entry into the file.
@jsulm
I'm a bit stuck at this moment.
By this, I can change the parameter in those particular line.QString filename = "config_keygrip"; QString path = QCoreApplication::applicationDirPath()+"/"+filename+".txt"; QFile file(path); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::information(this, "Unable to open file for read", file.errorString()); return; } else { QTextStream in(&file); while(!in.atEnd()) { QString line = in.readLine(); QString trackName("O CH1"); int pos = line.indexOf(trackName); if (pos >= 0) { QStringList list = line.split(' ', QString::SkipEmptyParts); QString currVal = QString::number(ui->verticalSlider->value()); list[3] = currVal; } } file.close(); }
But dont know where to open file for writing. Can someone show me how to do it?
-
@jsulm
I'm a bit stuck at this moment.
By this, I can change the parameter in those particular line.QString filename = "config_keygrip"; QString path = QCoreApplication::applicationDirPath()+"/"+filename+".txt"; QFile file(path); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::information(this, "Unable to open file for read", file.errorString()); return; } else { QTextStream in(&file); while(!in.atEnd()) { QString line = in.readLine(); QString trackName("O CH1"); int pos = line.indexOf(trackName); if (pos >= 0) { QStringList list = line.split(' ', QString::SkipEmptyParts); QString currVal = QString::number(ui->verticalSlider->value()); list[3] = currVal; } } file.close(); }
But dont know where to open file for writing. Can someone show me how to do it?
@viniltc said in Modify a .txt file:
But dont know where to open file for writing
You should know when you want to write back.
For example after you callfile.close();
if you want write back just after changing the line.
-
@jsulm
I'm a bit stuck at this moment.
By this, I can change the parameter in those particular line.QString filename = "config_keygrip"; QString path = QCoreApplication::applicationDirPath()+"/"+filename+".txt"; QFile file(path); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::information(this, "Unable to open file for read", file.errorString()); return; } else { QTextStream in(&file); while(!in.atEnd()) { QString line = in.readLine(); QString trackName("O CH1"); int pos = line.indexOf(trackName); if (pos >= 0) { QStringList list = line.split(' ', QString::SkipEmptyParts); QString currVal = QString::number(ui->verticalSlider->value()); list[3] = currVal; } } file.close(); }
But dont know where to open file for writing. Can someone show me how to do it?
@viniltc
I'm not going to write code for you, but I will tell you what you need to do where:First, after
list[3] = currVal;
you now need to reconstruct the new line fromlist
. Hint: since you usedQString::split()
to split it into aQStringList
look atQStringList::join()
.And second, as I wrote earlier, you have to decide whether you wish to output to temporary file as you go along reading or whether you want to hold the whole new output in memory and write back to original file at the end:
-
If write as go along: Open the temporary file for write immediately after you have opened the original file for read. Output a line at a time from your read loop. Close output file after closing input file, and then rename temporary output file to original input file.
-
If write at end: Store the output lines in memory from inside the read loop (e.g. into a
QStringList
). After you have closed input file from reading it, re-open it for overwrite. Send all lines from memory string list to file. Close file.
-