Hello!

I would like to change a single line inside a QFile (.txt) file, not changing anything else on it.

Now, as this (http://www.qtcentre.org/threads/4398...line-in-a-file) post tells, the easiest way of doing this is by using memory, and this is what I've implemented by now:

Qt Code:
  1. QString textoFinal;
  2. MReadWrite *mrw = new MReadWrite(this);
  3.  
  4. if (mrw->openRead(filenameNotes))
  5. {
  6. textoFinal.reserve(mrw->size() + 8); //Tomorrow = 8
  7.  
  8. while (!mrw->isAtEnd())
  9. {
  10. const QString strTemp = mrw->readLine() + "\n";
  11.  
  12. if (!strTemp.contains(nota->getTitulo()))
  13. textoFinal.append(strTemp);
  14. else
  15. {
  16. if (toWhichTab == TAB_FORTOMORROW)
  17. textoFinal.append("0" + itemSeparator + "Tomorrow" + strTemp.section(itemSeparator,1));
  18. else //if (toWhichTab == TAB_TODAY)
  19. textoFinal.append("0" + itemSeparator + strTemp.section("Tomorrow",1));
  20. }
  21. }
  22.  
  23. textoFinal.squeeze();
  24.  
  25. mrw->closeFile();
  26. }
  27. else
  28. FILE_NOT_OPENING;
  29.  
  30. if (mrw->openWrite(filenameNotes,QFile::Truncate))
  31. {
  32. if (!mrw->write(textoFinal))
  33. BUG_OCCURANCE("changeNoteTodayForTomorrow/write");
  34.  
  35. mrw->closeFile();
  36. }
  37. else
  38. FILE_NOT_OPENING;
  39.  
  40. delete mrw;
To copy to clipboard, switch view to plain text mode 

Note: MReadWrite is a class used to quiclky and easier write and read from text files. It implements QFile and QTextStream.
Note 2: it's irrelevant, but the code above is used to change a specific line in the code putting or taking out a "Tomorrow" string. "itemSeparator" is a default QString used to separate contents in the txt file.
Note 3: Yes, I know, I could be using QStringList, but anyway... :P


The problem, thought, is that this solution is quite bad when we are using huge text files. E.g., imagine I want to change the first line in a text file with 10.000 lines, each of them quite long. In that case, even with reserve/squeeze, the idea of huge memory comsumption in order to change one miserable single line seems quite inappropriate. Not to mention that reading from and writing to the hard disk is usually not understood as fast actions.

So my question is: is there a way to change a single line in file without having to appeal to reading the entire file into memory, changing the desired line and writing it all back to the file?

I already tried a solution such as:

Qt Code:
  1. bool MReadWrite::writeLine(const QString text)
  2. {
  3. /*!
  4.   * \abstract This function is intended to write only a line
  5.   * inside the file, making all the rest of the
  6.   * file intact.
  7.   *
  8.   * \pre *goToLine already used
  9.   */
  10.  
  11. if (!isReading() || !isWriting())
  12. return false;
  13.  
  14. const qint64 currPosition = getPosition();
  15. const int lineSize = getLineExtension();
  16.  
  17. QString strBlanck;
  18.  
  19. if (lineSize > 5)
  20. strBlanck.reserve(lineSize);
  21.  
  22. for (int aaa = 0; aaa < lineSize; aaa++)
  23. strBlanck.append(" ");
  24.  
  25. if (!write(strBlanck))
  26. return false;
  27.  
  28. goToPosition(currPosition);
  29.  
  30. return write(text);
  31. }
To copy to clipboard, switch view to plain text mode 

But this function had quite an error. To explain, it opens the file as a ReadWrite mode, pick the current QTextStream position, write on it a fully blanck line, return to the original position and then write the intendend text. Now this function worked very well if the new string (const QString text) is shorter than the original one; but if is size is bigger, than it causes a error of "eating" the next line:

Qt Code:
  1. //original text file data
  2. 1234567890
  3. 1234567890
  4. 1234567890
  5. 1234567890
  6.  
  7. //text file data with shorter new string
  8. XXXX
  9. 1234567890
  10. 1234567890
  11. 1234567890
  12.  
  13. //text file data with larger new string
  14. XXXXXXXXXXXX
  15. 34567890
  16. 1234567890
  17. 1234567890
To copy to clipboard, switch view to plain text mode 

And I have no idea about how to fix this.

Glad for any help!!



Obs.: btw, if you know a better way of creating a blanck QString without having to use a for with append(" "), I'ld be glad to know