ios::app和ios::ate有什么区别?

21

可能是重复问题:
C++文件处理:ios:app和ios:ate之间有什么区别?

这两种文件打开模式有什么区别?

ios:ate将get/put指针位置设置为文件末尾,因此读取/写入将从末尾开始,但是它与再次以附加模式打开文件的ios::app有何不同?

当我创建了一个ofstream并在`ios:app模式下打开它时,put流指针仍然指向开头,那么附加是如何工作的呢?

此外,我了解到ifstreamofstreamfstream是管理底层流缓冲区的高级类。

这是否意味着即使在ios:app模式下,我也可以从文件中读取数据?


1
基本上,app 总是在写入任何内容之前寻找结尾,而 ate 允许你在打开后寻找并保持在那里。请参见此问题 - chris
3个回答

41

app 来自“append”的缩写,表示所有输出都将被添加(附加)到文件末尾。换句话说,你不能在文件的其他位置上进行写入,只能在末尾进行。

ate 来自“at end”的缩写 - 当你打开它时,它将设置流的位置在文件末尾,但你可以自由移动它(寻找)并在任何地方写入。


@James:在这方面,“app” / “ate”与未使用这些标志打开的文件末尾的写入有什么不同?我认为它只是旨在省略一次查找以提供方便。我没有意识到有人希望它也为他们刷新流或确保文件完整性。 - Steve Jessop
1
@SteveJessop appfopen 中映射为 "a"。C 标准不要求原子性,因为并非所有系统都支持它,但 "a" 的原始意图是让实现在打开文件时使用 O_APPEND 标志。这确实会导致每次写入之前的原子寻址。如果其他进程正在向文件写入,则差异是可见的。当另一个进程向文件写入时,您在文件中的位置不会前进,您的下一次写入将覆盖它所写的任何内容。使用 app,您的下一次写入将始终追加(而且没有竞争)。 - James Kanze
@SteveJessop,当然,问题在于系统写入时发生。如果您编写相对较短的行,并以std::endl结尾(或使用FILE*设置了行缓冲),则可能是安全的。在我的大多数应用程序中,"probably" 不够好,因此我实现了自己的streambuf - James Kanze
@James:当然,我同意那可能不够好。我怀疑我甚至从未尝试过在进程之间共享文件时使用O_APPENDapp,所以我从未意识到app几乎但并非完全有助于解决这个问题。谢谢。 - Steve Jessop
1
@SteveJessop 如果您的应用程序有多个进程,并且您想要一个共同的日志文件,则这很有用。如果紧接着fopen( ..., "a" )是一个返回0的setvbuf( ... _IOLBF _ ... ),并且您从未输出超过缓冲区长度的行,则它可以工作。在遵守setvbuf的实现上(所有Unix实现?至少我从未遇到过不遵守的)。同样,如果您调用filebuf::pubsetbuf并使用ofstreamstd::endl,则也是如此。(同样,如果实现遵守setbuf)。 - James Kanze

15

ate指定文件打开方式为在打开后直接将位置指针置于文件结尾,除此之外无其他操作。对于ofstream而言并不是很有用,除非使用其它标记,因为文件会被截断,所以文件的开头就是结尾。(如果要避免截断,并仍然能够在文件中任意写入,则需要同时加入 ios::in 标记,即使您不打算读取文件。)

app防止现有文件被截断,使每次写入都追加到文件末尾。如果可能的话,追加操作应该是原子性的;如果其他进程正在向文件写入,则你的写入仍应追加到文件末尾。但请注意,这是指实际的系统级写入。然而,如果您写入的行比缓冲区大小小,并且每行都以 std::endl 结束,那么您可以保证每行都会以原子方式追加,而不管其他进程是否在处理该文件。为了有效,您可能还需要在 filebuf 上使用 pubsetbuf,以确保最小缓冲区大小。

实际上,我从未使用过其中任何一个,也没有发现它们有任何用处。特别是 app 的缓冲问题通常会导致我编写自己的 streambuf,具有概念上无限的缓冲区(作为缓冲区的 std::vector<char>),它使用等效于 app 的底层系统文件打开方式,但仅在显式刷新时才写入(如 `std::endl` 所示)。


11

如果您查看例如此参考资料,您将会看到:

app     seek to the end of stream before each write 

ate     seek to the end of stream immediately after open 

这意味着ios::app只会在文件末尾进行写入,而ios::ate默认会在文件末尾读取和写入。但是,使用ios::ate可以自由地在文件中寻找位置,但是使用ios::app时,无论您设置的写指针位置在哪里,都将始终在文件末尾进行写入。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接