21

Possible Duplicate:
C++ Filehandling: Difference between ios:app and ios:ate?

What is the difference between these two file opening modes ?

ios:ate sets the get/put pointer position to the end of the file so reading/writing will begin from end, but how is it different from ios::app, which again opens a file in append mode?

When I have created a ofstream and opened it in `ios:app mode, the put stream pointer still points to the beginning, how does the appending work then?

Also, I understand that ifstream, ofstream, and fstream are high-level classes to manage the underlying stream buffer.

Does it mean that even in ios:app mode I can read data from a file?

Arun
  • 3,138
  • 4
  • 30
  • 41
  • 1
    Basically `app` always seeks to the end before writing anything, whereas `ate` lets you seek after opening and keeps it there. See [this question](http://stackoverflow.com/questions/10359702/c-filehandling-difference-between-iosapp-and-iosate). – chris Oct 17 '12 at 07:38

3 Answers3

41

app comes from 'append' - all output will be added (appended) to the end of the file. In other words you cannot write anywhere else in the file but at the end.

ate comes from 'at end' - it sets the stream position at the end of the file when you open it, but you are free to move it around (seek) and write wherever it pleases you.

GCB613
  • 174
  • 13
tozka
  • 3,211
  • 19
  • 23
  • @James: how is `app` / `ate` any different in this respect from writes to the end of files that *weren't* opened with those flags? I thought it was just intended as a convenience to save one seek. I didn't realise anyone expected it to also flush the stream for them, or otherwise ensure file integrity. – Steve Jessop Oct 17 '12 at 08:47
  • 1
    @SteveJessop `app` maps to `"a"` in `fopen`. The C standard doesn't require atomicity, because not all systems can support it, but the original _intent_ of `"a"` was for the implementation to use the `O_APPEND` flag when opening the file. Which does cause atomic seek to end before each write. The difference is visible if other processes are writing to the file. When another process writes to the file, your position in the file doesn't advance, and your next write will overwrite whatever it has written. With `app`, your next write will append, regardless (and there is no race). – James Kanze Oct 17 '12 at 08:58
  • @SteveJessop And the problem, of course, is when the write to system occurs. If you're writing reasonably short lines, and terminating each with `std::endl` (or have set line buffering with `FILE*`), you're probably safe. In most of my applications, probably isn't good enough, so I implement my own `streambuf`. – James Kanze Oct 17 '12 at 09:01
  • @James: sure, I agree that probably isn't good enough. I suspect I've never even *tried* to use `O_APPEND` or `app` with files shared between processes, so I never realised that `app` almost-but-not-quite helps with that. Thanks. – Steve Jessop Oct 17 '12 at 09:03
  • 1
    @SteveJessop It's useful if your application has several processes, and you want a common log file. `fopen( ..., "a" )` works _if_ it is immediately followed by a `setvbuf( ... _IOLBF _ ... )` which returns 0, and you never output a line longer than the buffer length. On an implementation which respects `setvbuf`. (All Unix implementations? At least, I've never encountered one that didn't.) Similarly if you call `filebuf::pubsetbuf` and use `std::endl` with `ofstream`. (Again, if the implementation respects `setbuf`.) – James Kanze Oct 17 '12 at 09:28
15

ate simply positions you at the end of file after opening, and nothing else. It's not much use on an ofstream, at least without other flags, since the file will have been truncated anyway, so the beginning is the end. (To avoid truncation, and still be able to write anywhere in the file, you need to or in ios::in as well, even if you're not going to read.)

app prevents the truncation of an existing file, and causes every write to go to the end of the file. Atomically, if possible; if other processes are writing to the same file, your write should still go to the end. Note however that this refers to the actual system level write. If, however, you are writing lines which are less than the buffer size, and you terminate each line with std::endl, you can count on each line being appended atomically, regardless of what other processes might be doing with the file. To be effective, you'll probably want to use pubsetbuf on the filebuf as well, to ensure a minimum buffer size.

In practice, I don't think I've ever used either of them, or found them of any use. The buffering issues with app, in particular, have generally led me to write my own streambuf, with conceptually unlimited buffering (an std::vector<char> as buffer), which opens the underlying system file with the equivalent of app, but guarantees only writing to it when explicitly flushed (as with `std::endl).

James Kanze
  • 150,581
  • 18
  • 184
  • 329
11

If you look at e.g. this reference, you will see:

app     seek to the end of stream before each write 

and

ate     seek to the end of stream immediately after open 

This means that ios::app only writes at the end, but that ios::ate reads and writes at the end by default. However, with ios::ate you can seek freely in the file, but with ios::app you will always write at the end, no matter what position you set for the writing pointer.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621