1

Application uses RapidXML to edit XML file. Editing is not automated and takes place occasionally: XML content is displayed in GUI and user performs some actions which change XML. Each change must be saved to disk immediately.

Loading RapidXML document object requires copying the content of the file into a string. Each change in a document is followed by copying the content of the document object back into the file.

File is used both for input and output in this example. Shall a single std::fstream object be used for all input/output operations in this case? It would be opened once, at the application startup, used for input/output, and closed at the end of the application.

Or, shall local (temporary) instances of std::ifstream and std::ofstream be used whenever file input/output needs to be performed? E.g. std::ifstream to be used at the beginning for reading the file (open, read, close); similarly, std::ofstream instance to be used whenever DOM must be exported into the file (open, write, close).

I am not concerned about performances here (due to the nature of the application) but am curious about the proper choice of file stream objects in this case.

Bojan Komazec
  • 8,186
  • 2
  • 33
  • 48

2 Answers2

3

Editing files in place when the amount of data to re-write is different from the original data is a real pain. If your file format requires data to be sequential and has no syntax for holes, then you don't really have a choice but to re-write the file (at least from the start of the modified position).

Also, there are additional constraints. If you require the data to be flushed to disk before continuing, then you might be able to use a single std::fstream for multiple edits. Operating systems typically don't flush the file to disk even when you invoke the flush() method on file streams. Some platforms offer non-portable solutions to really force a write. So if you need it to be flushed to disk, your best bet is to actually close the file.

Thus, especially for critical applications, I would recommend the 2nd approach (ifstream at initial load, ofstream at each write). I would also recommend writing to a temporary file, then moving the complete re-write to the preferred location, replacing the original files. This ensures you won't have any data loss (at least on systems that offer atomic file move).

André Caron
  • 41,491
  • 10
  • 58
  • 117
2

I'd definitely favor local temporary instances of std::ifstream and std::ofstream. I'm not even sure it would work otherwise; opening an std::ofstream empties the contents of an existing file. Just seeking to the beginning and overwriting doesn't remove any previous contents, and if the results of the changes shorten the file, you'll still be left with leftover characters from the earlier contents.

James Kanze
  • 142,482
  • 15
  • 169
  • 310