我正在学习C ++中的文件处理,但这里有一个问题。我正在尝试读取文件。 此代码用于输出Hello World。但它输出0x22fed8。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream file;
file.open("test.txt",ios::in|ios::out);
file << "Hello World";
cout << file;
file.close();
return 0;
}
我做错了什么?
答案 0 :(得分:25)
正如其他人所指出的那样,直接将文件打印到流不起作用。打印文件内容需要打开从文件中读取的另一个流,或者将流的读取指针重新设置为开头,然后再次读取整个文件(正如其他人所示)。
C ++不会自动执行此操作,但您可以手动执行此操作(此处打开新流):
ifstream ifs("filename");
现在,将文件内容写入另一个流是一个微不足道的补充。不要编写文件,只需编写文件缓冲区:
cout << ifs.rdbuf() << endl;
这就是全部!逐行读取文件不需要循环。
虽然我们讨论的是循环,但要注意以下列方式在循环中读取文件的代码:
while ( !file.eof() )
当出现读数错误时,此代码会产生无限循环。这种情况在很多很多情况下都会发生。考虑例如您在读取文件时删除该文件,或者某人删除了包含该文件的USB设备或该文件格式错误。所有这些情况都会在这里创建一个无限循环。 从不仅测试流中的eof
。
幸运的是,解决这个问题的方法也很简单。此外,它解释了为什么你的原始代码产生了如此奇怪的结果。实际上,C ++中的流具有隐式转换为 bool
- 类似类型。出于其他地方解释的原因(提示:safe bool idiom),它实际上已转换为void*
。
这样可以轻松测试流是否处于有效的非结束状态,并且可以安全地从中读取。因此,我们可以适当地重新制定循环:
while (file) …
上述代码依赖于转换为void*
。任何非null
指针都表示有效的流。现在,代码中也会出现同样的情况:
cout << file;
由于operator <<
没有适当的重载来获取流,因此C ++会查找其他重载并找到指针的重载。所以它隐含地调用了这样的东西:
cout << static_cast<void*>(file);
我已经解释了上面一个简单,有效的解决方案。但是,此解决方案需要重新打开文件并再次将其读取到内存中。这使所需的工作增加了一倍。我们可以通过引入一个类似于流的新类来实现这一点,并且实际上将每个输出一次发送到两个流。这样,您可以同时将数据写入文件和标准流。无需重新读取文件。
这个课本身很简单。以下完整代码演示了一般原则:
#include <iostream>
#include <fstream>
struct sinkpair {
sinkpair(std::ostream& a, std::ostream& b) : a(a), b(b) { }
// Forward all ouputs to both streams.
template <typename T>
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;
}
答案 1 :(得分:12)
编辑:有mrree的建议。
ifstream fin("file.txt");
if (fin.is_open() == false) {
// error
}
string line;
while( getline(fin, line) ) {
cout << line;
}
答案 2 :(得分:7)
让我们检查一下
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();
答案 3 :(得分:6)
#include <iostream>
#include <fstream>
int main(int, char **)
{
std::ifstream input("test.txt");
char c;
while (input >> c) {
std::cout << c;
}
return 0;
}
不要包含整个标准命名空间。 如果您想要输入文件流,请使用ifstream。
您想输出文件的内容,而不是文件。
如果要写入文件,请将其读回并发送到stdout,
#include <iostream>
#include <fstream>
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;
}
Konrad有最好的答案,但请考虑高级方法:
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iterator>
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<char>(file),
std::istream_iterator<char>(),
std::ostream_iterator<char>(std::cout)
);
return 0;
}