我正在学习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;
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
Kon*_*lph 25
正如其他人所指出的那样,直接将文件打印到流不起作用.打印文件内容需要打开另一个从文件读取的流,或者将流的读指针重新设置为开头,然后再次读取整个文件(正如其他人所示).
C++不会自动执行此操作,但您可以手动执行此操作(此处,打开新流):
ifstream ifs("filename");
Run Code Online (Sandbox Code Playgroud)
现在,将文件内容写入另一个流是一个微不足道的补充.只需编写文件缓冲区,而不是编写文件:
cout << ifs.rdbuf() << endl;
Run Code Online (Sandbox Code Playgroud)
就这样!逐行读取文件不需要循环.
当我们讨论循环时,请注意以下列方式在循环中读取文件的代码:
while ( !file.eof() )
Run Code Online (Sandbox Code Playgroud)
当出现读数错误时,此代码会产生无限循环.这种情况在很多很多情况下都会发生.考虑例如,在您阅读文件时删除文件,或者有人删除包含该文件的USB设备或文件格式错误.所有这些情况都会在这里创建一个无限循环.永远不要只eof
在溪流中测试.
幸运的是,这个问题的解决方案也很简单.此外,它解释了为什么你的原始代码产生了如此奇怪的结果.事实上,C++中的流有一个隐式转换为类似bool
的类型.由于其他地方解释的原因(提示:安全bool成语),它实际上转换为void*
.
这样可以轻松测试流是否处于有效,非最终状态并且可以安全地读取.因此,我们可以适当地重新构造循环:
while (file) …
Run Code Online (Sandbox Code Playgroud)
上面的代码依赖于转换void*
发生.任何非null
指针都表示有效的流.现在,代码中也会出现同样的情况:
cout << file;
Run Code Online (Sandbox Code Playgroud)
由于没有适当的重载operator <<
需要流,C++寻找其他重载并找到指针的重载.所以它隐含地调用这样的东西:
cout << static_cast<void*>(file);
Run Code Online (Sandbox Code Playgroud)
我已经解释了上面一个简单,有效的解决方案.但是,此解决方案需要重新打开文件并再次将其读取到内存中.这使所需的工作增加了一倍.我们可以通过引入一个类似于流的新类来实现这一点,并且实际上将每个输出一次发送到两个流.这样,您可以同时将数据写入文件和标准流.无需重新读取文件.
这个课本身很简单.以下完整代码演示了一般原则:
#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;
}
Run Code Online (Sandbox Code Playgroud)
And*_*nko 12
编辑:有mrree的建议.
ifstream fin("file.txt");
if (fin.is_open() == false) {
// error
}
string line;
while( getline(fin, line) ) {
cout << line;
}
Run Code Online (Sandbox Code Playgroud)
让我们来看看这条线
cout << file;
Run Code Online (Sandbox Code Playgroud)
这个输出数字的原因是因为引擎盖下的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();
Run Code Online (Sandbox Code Playgroud)
#include <iostream>
#include <fstream>
int main(int, char **)
{
std::ifstream input("test.txt");
char c;
while (input >> c) {
std::cout << c;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
不要包含整个标准命名空间.如果需要输入文件流,请使用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;
}
Run Code Online (Sandbox Code Playgroud)
康拉德有最好的答案,但考虑高级方法:
#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;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
34971 次 |
最近记录: |