【问题标题】:writing after reading using fstream使用 fstream 读后写
【发布时间】:2014-09-15 08:03:50
【问题描述】:

我的印象是fstream c++ 中的对象可以用于读取和写入,使用相同的流。 我已经成功地能够先写入流,然后从中读取。但是,如果我再次尝试写入,则文件不会受到影响。

这是一个使用 MinGw 在 windows 上成功编译的代码示例:

int main()
{
    std::string path="file.txt";

    std::fstream fs(path.c_str());
    int buffSize=100;
    int bytesRead=0;
    char* buffer=new char[buffSize];

    fs.write("hello", 5);
    fs.seekp(0, std::ios::beg);
    fs.read(buffer, buffSize);
    bytesRead=fs.gcount();
    for(int i=0;i<bytesRead;i++) {std::cout << buffer[i];}
    std::cout << "\n";
    fs.clear();
    fs.seekp(1, std::ios::beg);
    fs.write("E", 1);
    std::cout << "fail: " << fs.fail() << "\n";

    delete[] buffer;
}

“file.txt”的初始内容只有:

AAAAAAA

程序输出:

helloAA
fail: 0

运行程序后在文本编辑器中查看文件显示最终内容为:

helloAA

最后写的“E”没有生效,为什么会这样,如何解决?

编辑:

我尝试使用fs.clear(),然后按照用户 0x499602D2 的建议再次写入。还添加了一行打印出是否设置了故障位或坏位并更新了程序输出。最终文件内容保持不变,但问题仍然存在。

【问题讨论】:

  • clear() 第一个read()之后的流。
  • @0x499602D2 单独没有解决它,至少对我来说没有。
  • 应该的。读取整个文件设置eof 标志,clear 将其清除,因此查找和写入成功。如果您在代码中检查错误,您会看到失败的地方。
  • 你有没有试过在写操作后在流对象上调用flush()?我的猜测是再次写入后数据没有刷新到文件中。

标签: c++ io fstream


【解决方案1】:

一旦你使用 fstream 读取一个文件,tellg 和tellp 指向-1。 为了能够使用 fstream 再次写入,只需调用 fstream.clear(),它会将读写指针重置到读取之前的位置。

上面发布的解决方案都不起作用,但 fstream.clear() 有效。

【讨论】:

    【解决方案2】:
    string data="";
    string Newdata="New Data";
    std::fstream output_file(fileName,  ios::in| ios::out);
    output_file >> data; //read Data
    
     output_file.seekg( 0, ios::beg );//set point to zero
     output_file<<Newdata<<"\n"; //write new Data
     output_file.close();
    

    【讨论】:

      【解决方案3】:

      这项工作适用于 GCC 4.9.0 和 VS2013。

      注意事项:

      • seekg 用于移动读取指针
      • seekp 用于移动写指针

      在fs.seekp(0, std::ios::beg); 行的示例代码中需要查找。没有问题,因为读取指针没有移动(直到那里没有读取)。

      代码:

      #include <algorithm>
      #include <iostream>
      #include <fstream>
      
      using namespace std;
      
      int main(int argc, char* argv[]) {
        std::string path = "H:\\save.txt";
      
        int buffSize = 100;
        int bytesRead = 0;
        char* buffer = new char[buffSize];
      
        std::fstream fs(path.c_str());
        fs.write("hello", 5);
        fs.flush();                        // flushing to disk file
        fs.seekg(0, std::ios_base::beg);   // moving the read pointer
        fs.read(buffer, buffSize);
        bytesRead = fs.gcount();
        for (int i = 0; i < bytesRead; i++) {
          std::cout << buffer[i];
        }
        std::cout << "\n";
        fs.clear();
        fs.seekp(1, std::ios::beg);
        fs.write("E", 1);
        fs.flush();                      // flushing to disk file
        std::cout << "fail: " << fs.fail() << "\n";
      
        delete[] buffer;
      
        return 0;
      }
      

      【讨论】:

        【解决方案4】:

        (从我在 cmets 中发布的关于这个问题的更详细的答案)

        您需要在输出流对象(从 ostream 派生)上调用 flush(),以便将数据实际写入输出流。有关flush() 的更多信息,请访问on this c++ reference page。

        【讨论】:

        • 这个因素完全超出了我的想象。很久没有考虑缓冲了。
        • 不接受替代品! cppreference.com 是最好的 C++ 参考; cplusplus.com 最近添加了“C++ 参考”标语作为他们正在进行的 SEO 游戏的一部分。
        猜你喜欢
        • 1970-01-01
        • 2016-01-30
        • 2012-04-05
        • 1970-01-01
        • 1970-01-01
        • 2016-05-11
        • 2021-03-23
        • 2013-07-06
        相关资源
        最近更新 更多