C++ 如何将单个文件同时链接到两个不同的流?
如果在同一程序中写入上述两行,则不会产生任何错误或警告。 但是我们怎么能同时写入和读取同一个文件呢。C++ 如何将单个文件同时链接到两个不同的流?,c++,C++,如果在同一程序中写入上述两行,则不会产生任何错误或警告。 但是我们怎么能同时写入和读取同一个文件呢。 这是怎么回事x;//产生42 因此,编译器没有理由发出警告或给出错误。如果要在运行时检查文件打开是否成功,只需检查它。此处的输入是字符串。编译器不可能知道您做错了什么。我不是说它是。嗯,这个问题写得有点糟糕。你是程序员,因此你对程序产生的警告和错误负责。然而,语言通常允许您检查对象的状态。您可以做的是检查两个流是否都实际打开。有趣的是,我在标准中找不到任何东西可以定义这种情况下的行为,或者显式
这是怎么回事在C++标准中没有任何东西排除这个问题——请求只是传递给操作系统,它可能允许或不允许。 例如,在某些操作系统/文件系统组合上,如果要创建与现有文件同名的文件,操作系统会隐藏现有文件的目录条目,以便其他应用程序无法打开它,但使用它的现有进程将能够继续这样做;当他们全部关闭时,文件将被删除。同时,可以使用相同的名称创建一个新文件,之后打开该文件的任何应用程序都将看到刷新到该新文件的内容 在其他系统上,可能会生成某种类型的“正在使用”或“锁定”错误消息,导致
失败
/坏
状态处于std::ofstream
状态
您应该始终测试文件流创建是否成功,例如:
ifstream fin("test.txt");
ofstream fout ("test.txt");
if(std::ifstream in(“filename.txt”))
…用于。。。
其他的
因此,正如评论所说,编译器本身并不真正知道您想要实现什么(当然,在某些情况下,您实际上希望实现类似的目标,例如):
根据操作系统(以及下面层中使用的标志),您可能能够实际执行这两行而不会出错—在Unix中,打开的文件在系统中保持打开状态,即使其他操作删除了该文件(第二行也可以),因此您可以读取“旧”文件,然后写入新文件。这当然不是“同时读取和写入同一文件”,而是读取一个文件并写入另一个文件。而在大多数非Unix文件系统中,这将不起作用,因为操作系统将对两个调用使用相同的目录条目,并打开现有文件,然后第二个调用将使文件为空或失败(取决于操作系统等)
如果您真的想读写同一个文件,解决方案是:
打开文件时,使用ios_base::in | ios_base::out
作为标志李>
在输出端使用临时文件,并在“完成”后重命名该文件。由于大多数类型的文本文件更改都要求“重写”文件(除了在末尾添加内容),因此这通常是首选方法。然后,在完成更改后,将新文件重命名为旧文件(首先删除原始文件的部分)。这也意味着即使程序崩溃,您也至少有一个完整的文件(尽管名称错误)
编译器并没有理由理解你们做错了什么,它不会记住你们在程序中使用过的所有文件名。此外,如果文件名来自用户输入或仅仅来自变量,编译器永远无法猜测它们是否相同:
ifstream fin("test.txt");
ofstream fout ("test.txt");
事实上,您的案例(硬编码文件名)是非常不寻常的情况,所以我认为这样的警告在一般情况下是没有用的
除此之外,这些代码有时甚至可以正常工作
例如,如果test.txt
是一个命名管道,则可以安全地同时打开它进行读写。您仍然需要做一些变通来防止阻塞,最简单的方法是在不同的线程中打开管道。但您可以安全地想象一种情况,命名管道操作不会阻塞(我不知道在流行的操作系统中是否可以通过某些操作系统选项进行阻塞,但无论如何,您可以想象这样的操作系统),在这种情况下,以下代码应该可以正常工作:
ifstream fin(s1);
ofstream fout (s2); // is s1==s2?
//(对于命名管道操作不阻塞的虚拟操作系统)
ifstream fin(“测试先进先出”);
流fout(“test.fifo”);
fout>x;//产生42
因此,编译器没有理由发出警告或给出错误。如果要在运行时检查文件打开是否成功,只需检查它。此处的输入是字符串。编译器不可能知道您做错了什么。我不是说它是。嗯,这个问题写得有点糟糕。你是程序员,因此你对程序产生的警告和错误负责。然而,语言通常允许您检查对象的状态。您可以做的是检查两个流是否都实际打开。有趣的是,我在标准中找不到任何东西可以定义这种情况下的行为,或者显式地将其标记为未定义。您可以使用带有std::ios_base::in | std::ios_base::out的流
ifstream fin("test.txt");
ofstream fout ("test.txt");
ifstream fin(s1);
ofstream fout (s2); // is s1==s2?
// (for imaginary OS where named pipe operations do not block)
ifstream fin("test.fifo");
ofstream fout("test.fifo");
fout << 42;
int x;
fin >> x; // produces 42