C++ 如何将单个文件同时链接到两个不同的流?

C++ 如何将单个文件同时链接到两个不同的流?,c++,C++,如果在同一程序中写入上述两行,则不会产生任何错误或警告。 但是我们怎么能同时写入和读取同一个文件呢。 这是怎么回事x;//产生42 因此,编译器没有理由发出警告或给出错误。如果要在运行时检查文件打开是否成功,只需检查它。此处的输入是字符串。编译器不可能知道您做错了什么。我不是说它是。嗯,这个问题写得有点糟糕。你是程序员,因此你对程序产生的警告和错误负责。然而,语言通常允许您检查对象的状态。您可以做的是检查两个流是否都实际打开。有趣的是,我在标准中找不到任何东西可以定义这种情况下的行为,或者显式

如果在同一程序中写入上述两行,则不会产生任何错误或警告。 但是我们怎么能同时写入和读取同一个文件呢。
这是怎么回事 在其他系统上,可能会生成某种类型的“正在使用”或“锁定”错误消息,导致
失败
/
状态处于
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