为什么我不能在Mac OS X上阅读和追加std :: fstream?

时间:2010-02-21 09:43:37

标签: c++ stl cross-platform fstream

考虑以下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

在我的机器(Snow Leopard)上,它什么都没打印出来。仔细观察,第一次调用getline失败了。奇怪的是,如果我添加第二行也会失败:仍然没有打印任何内容!

任何人都可以解开这个谜团吗?

2 个答案:

答案 0 :(得分:9)

当你说:

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 ++。

答案 1 :(得分:2)

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

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

更新:实际上该文件可能已被打开,但处于追加模式 - 请参阅Neii的回答。

更新2:好的,又错了。至少在Leopard的g ++中,不会打开该文件,因为app标志与in标志不兼容。因此,上述检查将打印Oh dear

在MSVC ++中,它继续并打开文件,显然是在开头的读取位置,这解释了为什么其他人看到它的工作,我为怀疑他们的真实性而道歉!