我正在学习C++中的文件处理,但这里有一个问题.我正在尝试读取文件.此代码用于输出Hello World.但它输出0x22fed8.
#include#include using namespace std; int main() { fstream file; file.open("test.txt",ios::in|ios::out); file << "Hello World"; cout << file; file.close(); return 0; }
我究竟做错了什么?
正如其他人所指出的那样,直接将文件打印到流不起作用.打印文件内容需要打开另一个从文件读取的流,或者将流的读指针重新设置为开头,然后再次读取整个文件(正如其他人所示).
C++不会自动执行此操作,但您可以手动执行此操作(此处,打开新流):
ifstream ifs("filename");
现在,将文件内容写入另一个流是一个微不足道的补充.只需编写文件缓冲区,而不是编写文件:
cout << ifs.rdbuf() << endl;
就这样!逐行读取文件不需要循环.
当我们讨论循环时,请注意以下列方式在循环中读取文件的代码:
while ( !file.eof() )
当出现读数错误时,此代码会产生无限循环.这种情况在很多很多情况下都会发生.考虑例如,在您阅读文件时删除文件,或者有人删除包含该文件的USB设备或文件格式错误.所有这些情况都会在这里创建一个无限循环.永远不要只eof
在溪流中测试.
幸运的是,这个问题的解决方案也很简单.此外,它解释了为什么你的原始代码产生了如此奇怪的结果.事实上,C++中的流有一个隐式转换为类似bool
的类型.由于其他地方解释的原因(提示:安全bool成语),它实际上转换为void*
.
这样可以轻松测试流是否处于有效,非最终状态并且可以安全地读取.因此,我们可以适当地重新构造循环:
while (file) …
上面的代码依赖于转换void*
发生.任何非null
指针都表示有效的流.现在,代码中也会出现同样的情况:
cout << file;
由于没有适当的重载operator <<
需要流,C++寻找其他重载并找到指针的重载.所以它隐含地调用这样的东西:
cout << static_cast(file);
我已经解释了上面一个简单,有效的解决方案.但是,此解决方案需要重新打开文件并再次将其读取到内存中.这使所需的工作增加了一倍.我们可以通过引入一个类似于流的新类来实现这一点,并且实际上将每个输出一次发送到两个流.这样,您可以同时将数据写入文件和标准流.无需重新读取文件.
这个课本身很简单.以下完整代码演示了一般原则:
#include#include struct sinkpair { sinkpair(std::ostream& a, std::ostream& b) : a(a), b(b) { } // Forward all ouputs to both streams. template sinkpair& operator <<(T const& value) { a << value; b << value; return *this; } // Explicit overload needed for manipulators such as `endl`. sinkpair& operator <<(std::ostream& (*manip)(std::ostream&)) { a << manip; b << manip; return *this; } private: std::ostream& a; std::ostream& b; }; int main() { std::ofstream ofs("test.txt"); sinkpair sp(std::cout, ofs); sp << "Hello" << std::endl; }
编辑:有mrree的建议.
ifstream fin("file.txt"); if (fin.is_open() == false) { // error } string line; while( getline(fin, line) ) { cout << line; }
让我们来看看这条线
cout << file;
这个输出数字的原因是因为引擎盖下的fstream是一个文件指针.通过将文件传递给cout,你基本上要求一个fout的cout.这将默认为文件的基础句柄的值.
如果要输出文件的内容,则需要将其读入并逐行输出.
fstream file; file.open("test.txt",ios::in|ios::out); file << "Hello World"; file.seekg (0, ios::beg); while ( !file.eof() ) { string temp; file >> temp; cout << temp << std::eol; } file.close();
#include#include int main(int, char **) { std::ifstream input("test.txt"); char c; while (input >> c) { std::cout << c; } return 0; }
不要包含整个标准命名空间.如果需要输入文件流,请使用ifstream.
您想要输出文件的内容,而不是文件.
如果要写入文件,请将其读回并发送给stdout,
#include#include int main(int, char **) { std::fstream file("test.txt",std::ios::in|std::ios::out); file << "Hello" << std::endl; file.seekp(std::ios::beg); char c; while (file >>c) { std::cout << c ; } return 0; }
康拉德有最好的答案,但考虑高级方法:
#include#include #include #include int main(int, char **) { std::fstream file("test.txt",std::ios::in|std::ios::out); file << "Hello" << std::endl; file.seekp(std::ios::beg); std::copy( std::istream_iterator (file), std::istream_iterator (), std::ostream_iterator (std::cout) ); return 0; }