Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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()



  • @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.



  • @viniltc hi

    for the read/write part you can use JSON document instead of plain text file, because it offers you convenient methods for "parsing" the file


  • Lifetime Qt Champion

    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 :)



  • I want to replace number 180 with a different value get through a QSlider

    Can the value be represented always with 3 digits (decimal or hex doesn't matter)?
    What encoding is the text file using?



  • @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();
        }
    
    

  • Qt Champions 2019

    @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.



  • This post is deleted!


  • @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?


  • Qt Champions 2019

    @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 call

    file.close();
    

    if you want write back just after changing the line.



  • @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 from list. Hint: since you used QString::split() to split it into a QStringList look at QStringList::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.



  • @JonB Thanks a lot for your feedback :)


Log in to reply