代码之家  ›  专栏  ›  技术社区  ›  Andres Jaan Tack

为什么我不能在Mac OS X上读取并附加std::fstream?

  •  2
  • Andres Jaan Tack  · 技术社区  · 16 年前

    考虑下面的C++程序,它使用一个文件并打印每一行。它是一个较大程序的一部分,稍后我将根据所见内容附加到该文件中。

    #include <fstream>
    using std::fstream;
    #include <iostream>
    #include <string>
    using std::string;
    
    int main()
    {
     fstream file("file.txt", fstream::in | fstream::out | fstream::app);
    
     string line;
     while (std::getline(file, line))
      std::cerr << line << std::endl;
    
     return 0;
    }
    

    现在应用此版本的 file.txt (第一行有一个词,后面跟着一个新行):

    Rain
    

    在我的机器上(雪豹),这个什么也不打印。仔细检查后,第一次调用getline失败。奇怪的是,如果我添加第二行,它也会失败:仍然没有打印内容!

    有人能解开这个谜吗?

    2 回复  |  直到 16 年前
        1
  •  9
  •   anon    16 年前

    当你说:

    fstream file("file.txt", fstream::in | fstream::out | fstream::app);
    

    在附加模式下打开文件-即在末尾。只需在读取模式下打开:

    fstream file("file.txt", fstream::in );
    

    或者使用ifstream:

    ifstream file("file.txt" );
    

    当然,正如Earwicker所建议的,你应该经常测试公开赛是否成功。

    如果决定以追加模式打开,则可以显式移动读取指针:

    #include <fstream>
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main() {
        fstream file( "afile.txt", ios::in | ios::out | ios::app );
        if ( ! file.is_open()  ) {
            cerr << "open failed" << endl;
            return 1;
        }
        else {
            file.seekg( 0, ios::beg );   // move read pointer
            string line;
            while( getline( file, line ) ) {
                cout << line << endl;
            }
        }
    }
    

    编辑: 打开文件时使用的标志组合似乎会导致特定于实现的行为。上面的代码在Windows上与g++一起工作,但在Linux上与g++不一起工作。

        2
  •  2
  •   Daniel Earwicker    16 年前

    您应该检查文件是否已实际打开:

    if (!file)
        std::cerr << "Oh dear" << std::endl;
    

    更新: 事实上,该文件可能已打开,但处于附加模式-请参阅NEII的答案。

    更新2: 好吧,又错了。至少在Leopard的g++中,不会打开该文件,因为 app 标志与不兼容 in 标志。所以上面的支票会打印出来 Oh dear .

    在msvc++中,它继续打开文件,显然在开始时就有读取位置,这解释了为什么其他人看到它工作,我为怀疑它们的准确性而道歉!