C++ 如何打开文件进行阅读&;写,如果它不存在,创建它,而不截断它?

C++ 如何打开文件进行阅读&;写,如果它不存在,创建它,而不截断它?,c++,iostream,fstream,c++03,C++,Iostream,Fstream,C++03,对于std::fstream,我希望能够读取和写入文件的I/O标志的正确设置是什么?如果文件存在,则不截断文件,如果不存在,则创建文件 我试过了 std::ios::binary | std::ios::in | std::ios::out std::ios::binary | std::ios::in | std::ios::out | std::ios::ate 但是,如果文件不存在,这两种方法都不会创建该文件 我不想要std::ios::app,因为我还需要能够使用get和put游标随意

对于
std::fstream
,我希望能够读取和写入文件的I/O标志的正确设置是什么?如果文件存在,则不截断文件,如果不存在,则创建文件

我试过了

std::ios::binary | std::ios::in | std::ios::out
std::ios::binary | std::ios::in | std::ios::out | std::ios::ate
但是,如果文件不存在,这两种方法都不会创建该文件

我不想要
std::ios::app
,因为我还需要能够使用get和put游标随意查找文件


我想,一种解决方法是首先实例化一个
std::ofstream
,然后立即关闭它并打开我真正想要的流,但如果可以用一个流对象来避免的话,这看起来很混乱。

此时,我的结论是
std::ios::in
彻底阻止了这一点,我必须使用变通方法

因此:


读取
std::ios::binary
,您可能需要的剩余
openmode
是:

std::ios::in | std::ios::app
其效果就像打开文件时使用:

std::fopen(filename,"a+")
其效果是:

  • 打开或(如果不存在)创建用于读写的文件
  • 在文件末尾写入数据
如果使用此
openmode
std::fstream
的形式打开文件,则如果文件存在,它不会被截断。你可以 从文件中读取
fstream
tellg()\tellp()
指针指向的任何位置, 只要有东西可以读,你就可以定位那个指针 使用流的
seekg()\seekp()
进行读取。但是,所有写入操作都将被删除 附加到文件末尾

因此,除非您需要执行写操作,否则此openmode将适合您的账单
现有数据。

一项调查,从Linux的角度来看(尽管其中大部分可能适用于其他Unice):

在系统调用层,您需要
open(O|RDWR | O|u create,0666)
(但不是
O|u TRUNC
O|u APPEND
或一系列其他标志,尽管可以说所有文件都应该使用
O|u CLOEXEC | O|u LARGEFILE
打开,但这不是重点)

在libc层,没有标准的
模式
字符串表示
O_create
而没有
O_TRUNC
。但是,您可以使用
open
后跟
fdopen

在C++库级别,没有标准的方法传递希望的标志。但是,使用特定于实现的类/函数或第三方库是可能的;看



就我个人而言,我倾向于在C甚至系统调用级别进行所有I/O,因为API更好,更可预测。对于类实例的输入/输出,我有自己的模板。

创建尝试不需要进行失败检查或报告。另外,我认为您不需要在c++11及更高版本中使用
c_str()。Boost文件系统可能会为您做这件事(我不知道),如果是这样,那么您只需等到C++17即可@Cheersandhth.-Alf作为标记(c++03),似乎是
c_str()
的原因,尽管如果有人阅读这篇文章要使用c++11或更高版本,你显然是对的。顺便说一句,03x中没有包含std::string
构造吗?@WhozCraig:没有,C++03中唯一的新东西是值初始化。@cheers-sandhth.-Alf-ah.。那么所有这些
C_str
与该标记结合起来确实有意义。谢谢你的信息@轻量级在轨道上比赛,我相信你在调用
std::ostream
构造函数时忘记添加
std::ios::binary | std::ios::app
。如果没有这些标志,该文件将被截断,以防它已经存在,这是您说您不想要的。当我偶然发现这一点时,我也没有:)谢谢,关闭,但是:“我不想要
std::ios::app
,因为我还需要能够使用get和put游标随意查找文件。”
std::fopen(filename,"a+")