如何打开一个文件进行读写,如果它不存在则创建它而不截断它?

How can I open a file for reading & writing, creating it if it does not exist, without truncating it?

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,因为我还需要能够随意搜索文件,同时使用 getput个游标。

我想,一个解决方法是先实例化一个 std::ofstream,然后立即关闭它并打开我真正想要的流,但如果可以用单个流对象避免它,那似乎很麻烦。

目前,我的结论是 std::ios::in 完全可以防止这种情况发生,我必须使用解决方法。

所以:

if (!std::ostream(path.c_str()))
   throw std::runtime_error("Could not create/open file");

std::fstream fs(path.c_str(), std::ios::binary | std::ios::in | std::ios::out);
if (!fs)
   throw std::runtime_error("Could not open file");

// ... use `fs`

std::ios::binary为读,剩下的openmode可能是你需要的:

std::ios::in | std::ios::app

它的效果就像打开文件一样:

std::fopen(filename,"a+")

那个的效果是:

  • 打开或者如果不存在则创建文件进行读写
  • 在文件末尾写入数据。

如果您使用此 openmode 打开文件作为 std::fstream,如果它存在则不会被截断。你可以 从 fstreamtellg()\tellp() 指针指向的文件中读取, 前提是那里有东西要读,你可以定位那个指针 使用流的 seekg()\seekp() 进行阅读。但是,所有写入都将 附加到文件末尾。

除非您需要执行写入,否则此打开模式将符合您的要求 到现有数据中。

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

在系统调用层,你想要 open(O_RDWR | O_CREAT, 0666)(但不是 O_TRUNCO_APPEND 或一堆其他标志,尽管可以说所有文件都应该用 O_CLOEXEC | O_LARGEFILE, 但那不是重点)

在 libc 层,没有标准的 mode 字符串暗示 O_CREAT 没有 O_TRUNC。但是,您可以使用 open 后跟 fdopen.

在 C++ 库级别,没有传递所需标志的标准方法。但是,使用特定于实现的 classes/functions 或第三方库是可能的;见 How to construct a c++ fstream from a POSIX file descriptor?


就个人而言,我倾向于在 C 甚至系统调用级别执行所有 I/O,因为 API 更好并且更可预测。对于 class 个实例中的 input/output 个,我有自己的模板。