1

I have a graphical (Qt, C++) application that stores its state in a data file and updates that file every 60 seconds.

I wrote a function to prevent data loss when the application or the OS is interrupted during writing.

QString updateFileSafely( const QString & origFilePath, const QByteArray & newContent )
{
    QString newFilePath = origFilePath+".new";
    QFile newFile( newFilePath );
    if (!newFile.open( QIODevice::WriteOnly ))
    {
        return "Could not open file "%newFilePath%" for writing: "%newFile.errorString();
    }

    newFile.write( newContent );
    if (newFile.error() != QFile::NoError)
    {
        return "Could not write to file "%newFilePath%": "%newFile.errorString();
    }

    newFile.close();

    QFile oldFile( origFilePath );
    if (oldFile.exists())
    {
        if (!oldFile.remove())
        {
            return "Could not delete the previous file "%origFilePath%": "%oldFile.errorString();
        }
    }

    if (!newFile.rename( origFilePath ))
    {
        return "Could not rename the new file "%newFilePath%" back to "%origFilePath%": "%newFile.errorString();
    }

    return "";
}

This code should only remove the old file after the new file is successfully written and closed.
Yet my users (both Windows and Linux users) still keep comming to me with an issue that their data file is full of zero bytes after their OS crashed. I even tried adding sleep() after the newFile.close() but it had no effect.

I asked on Qt forum and was told that Qt does not do any caching or buffering internally and everything is passed to the OS right away, so if there is caching involved, it must be on the of OS or hardware.

My question is: What is the best practice when applications want to save data files containing for exampple user settings? What can i do to reduce the frequency of user data loss to minimum?

Youda008
  • 1,788
  • 1
  • 17
  • 35
  • 2
    Isn't this essentially QSaveFile? – perivesta Jul 07 '23 at 09:02
  • Maybe, this is a H/W or OS problem. It reminds me that I once heard about [Journaling file system](https://en.wikipedia.org/wiki/Journaling_file_system) (though this is a long time ago, and I was assuming such technique is used everywhere now). What platform are you on? – Scheff's Cat Jul 07 '23 at 09:07
  • FYI: [Force write of a file to disk](https://stackoverflow.com/q/13358431/7478597), [Force ofstream file flush on Windows](https://stackoverflow.com/q/4473064/7478597) – Scheff's Cat Jul 07 '23 at 09:12
  • 3
    The thing that you are missing and that `QSaveFile` presumably does for you is that you need to [`fsync`](https://linux.die.net/man/3/fsync) (or whatever you OS calls it) the changes to the disk before doing the renaming. – Homer512 Jul 07 '23 at 09:17
  • @Scheff'sCat Both Windows users and Linux users report this problem. I've added it to the question. – Youda008 Jul 07 '23 at 09:41
  • @Homer512 That sounds like that could be the right answer. – Youda008 Jul 07 '23 at 09:43

0 Answers0