考虑以下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失败了。奇怪的是,如果我添加第二行也会失败:仍然没有打印任何内容!
任何人都可以解开这个谜团吗?
答案 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 ++中,它继续并打开文件,显然是在开头的读取位置,这解释了为什么其他人看到它的工作,我为怀疑他们的真实性而道歉!