Find last of... and write above.



  • Hello to everyone.
    First of all thanks a lot for reading this post and being able to help.

    I have a .txt, for example:

    1. Hello world
    2. This world is really big...
    3. I love this world.
    

    What I would like is to write a line above the last line which contains "world.
    So in this case image that I want to write the line "This forum is amazing".
    So the .txt will have to be:

    1. Hello world
    2. This world is really big...
    3. This forum is amazing
    4. I love this world.
    

    So I have to:
    1º first find last word of world.
    2º Write above.

    How can I do that?
    Any help?

    thanks a lot!


  • Moderators

    @AlvaroS

    QFile file(fileName);
    if (file.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        // read lines
        QStringList lines;
        int lastIdx = -1;
        QTextStream in(&file);
        for( int i= 0; !in.atEnd(), ++i )
        {
            QString line = in.readLine();
            lines << line;
            if( line.contains("XXX") )
                lastIdx = i;
        }
    
        // insert your line
        lines.insert( lastIdx-1, ... );
        
        //write back to file
        file.seek(0);
        file.write( lines.join("\n") );
        
        file.close();
    }
    

    You should only use this code if the files aren't too big, since everything is loaded into the memory.
    Also i left out some error checking and it's untested, but it should give you an idea.


  • Moderators

    Here's a little shorter version, with a lot less allocations:

    //insert stuff before line with last occurrence
    void isblwlo(const QString& file, const QString& what, const QString& stuff)
    {
        QFile f(file);
        if (!f.open(QIODevice::ReadWrite | QIODevice::Text))
            return;
    
        QByteArray buff = f.readAll();
        int pos = buff.lastIndexOf(what);
        if (pos < 0)
            return;
    
        int endline_pos = buff.lastIndexOf("\n", pos) + 1;
        buff.insert(endline_pos,  stuff + "\n");
    
        f.seek(0);
        f.write(buff);
    }
    

    You could trim it down even more by not doing an insert and writing in three parts - up to endline_pos, stuff and after endline_pos. Then only one allocation would remain. I'll leave it as an exercise to the reader ;)

    Same warning applies - don't use for large files.



  • You've got a couple of C++ answers :) If you are looking for QML / Js answer. You can pass your new line into the <line> param and the original text into <txt> param. The code is pretty short and mostly self explanatory. You are dividing the text into an array of lines by using the new line character "\n" and then inserting a new line into the list and putting it back together as one blob of text.

    function insertAsSecondLastLine(line,txt) {
    	var arr = !txt ? [] : txt.split("\n")
    	if(arr.length > 0) {
    		var lineNumber = arr.length - 1
    		arr.splice(lineNumber,0,line);
    	}
    	else {
    		arr.push(line);
    	}
    	return arr.join("\n")
    }
    


  • @raven-worx said:

    @AlvaroS

    QFile file(fileName);
    if (file.open(QIODevice::ReadWrite | QIODevice::Text))
    {
        // read lines
        QStringList lines;
        int lastIdx = -1;
        QTextStream in(&file);
        for( int i= 0; !in.atEnd(), ++i )
        {
            QString line = in.readLine();
            lines << line;
            if( line.contains("XXX") )
                lastIdx = i;
        }
    
        // insert your line
        lines.insert( lastIdx-1, ... );
        
        //write back to file
        file.seek(0);
        file.write( lines.join("\n") );
        
        file.close();
    }
    

    You should only use this code if the files aren't too big, since everything is loaded into the memory.
    Also i left out some error checking and it's untested, but it should give you an idea.

    Hello my friend.
    First of all thanks a lot for answering.

    I have tried what you say like this:

        QString fileName = QFileDialog::getOpenFileName(this,"indicate world","/home","files World (*.world)"); // We use the QFileDialog class to obtein the whole name file that user has choosen.
        QFile file(fileName);
    
        if (file.open(QIODevice::ReadWrite | QIODevice::Text))
        {
            // read lines
            QStringList lines;
            int lastIdx = -1;
            QTextStream in(&file);
            for( int i= 0; !in.atEnd(); ++i )
            {
                QString line = in.readLine();
                lines << line;
                if( line.contains("world") )
                    lastIdx = i;
            }
    
            // insert your line
            lines.insert( lastIdx-1, "writting" );
    
            //write back to file
            file.seek(0);
            file.write( lines.join("\n") );
    
            file.close();
        }
    

    But it give an error in "file.write( lines.join("\n") );" which is:
    cpp:2106: error: no matching function for call to 'QFile::write(QString)'
    file.write( lines.join("\n") );
    ^
    Do you know why?

    Thanks!!



  • @Chris-Kawa said:

    Here's a little shorter version, with a lot less allocations:

    //insert stuff before line with last occurrence
    void isblwlo(const QString& file, const QString& what, const QString& stuff)
    {
        QFile f(file);
        if (!f.open(QIODevice::ReadWrite | QIODevice::Text))
            return;
    
        QByteArray buff = f.readAll();
        int pos = buff.lastIndexOf(what);
        if (pos < 0)
            return;
    
        int endline_pos = buff.lastIndexOf("\n", pos) + 1;
        buff.insert(endline_pos,  stuff + "\n");
    
        f.seek(0);
        f.write(buff);
    }
    

    You could trim it down even more by not doing an insert and writing in three parts - up to endline_pos, stuff and after endline_pos. Then only one allocation would remain. I'll leave it as an exercise to the reader ;)

    Same warning applies - don't use for large files.

    Thanks a lot, that works!


  • Moderators

    @AlvaroS said:

    But it give an error in "file.write( lines.join("\n") );" which is:
    cpp:2106: error: no matching function for call to 'QFile::write(QString)'
    file.write( lines.join("\n") );
    ^

    file.write( lines.join("\n").toUtf8() );
    


  • @raven-worx Thanks!!!
    This thread is solved :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.