在c++里,“流”可以理解为数据传输与操作的“介质”。
从输入输出角度来看,有输入流(比如cin)和输出流(cout)。对于输入流,数据通过它从外部设备(例如键盘)“流入”程序内部;对于输出流,程序内部的数据通过它“流向”外部设备(例如显示器)。也就是说,我们可以将“流”理解为数据的“介质”或者“载体”。
还有例如fstream相关的文件流。它能让程序与文件之间进行数据的读写,数据在程序与文件之间的流动,就是借助于流对象这个载体。而且流具有状态。
输入流与输出流,实际上是两个类istream和ostream。这两个类具有自己的成员函数。既然如此,我们要进行输入输出的时候,就不一定非得用cin与cout了,我们可以自定义istream和ostream对象,比如定义一个istream对象叫input,定义一个ostream对象叫output,那么input>>和cin>>,output<<和cout<<的效果是一样的。只不过,cin和cout已经和标准的输入输出设备(键盘和显示器)关联好了。
再来说文件流。当我们想要向计算机中的文件写入内容(或者导出其中的内容),我们就不能仅仅定义一个普通的输入流对象,因为我们的重点是要向文件内部写入数据,而不是向程序写入数据。但是,这本质上还是在解决输入输出的问题,只不过解决的是针对计算机内部的文件进行输入或输出的问题。
在C++中使用文件流,需要包含fstream头文件,它包含ifstream(用于从文件中读取数据)与ofstream(用于向文件写入数据)和fstream(既能读又能写)这几个类。
比如要向文件中写入数据,使用ofstream类,示例如下:
#include <iostream>
#include <fstream>
using namespace std;int main()
{ofstream outFile("example.txt");//构造函数,将文件与程序连接起来if (outFile.is_open()) //成员函数,用来判断文件是否打开{outFile << "这是要写入文件的内容" << endl;outFile.close();//成员函数,用来关闭文件} else {cout << "无法打开文件" << endl;}return 0;
}
从文件读取数据则使用ifstream类,示例如下:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;int main() {ifstream inFile("example.txt");if (inFile.is_open()) {string line;while (getline(inFile, line)) {cout << line << endl;}inFile.close();} else {cout << "无法打开文件" << endl;}return 0;
}
这里我们剖析一下getline().getline()的功能是逐行读取文件中的内容,将其读入字符串line中。为什么要使用while循环?是因为字符串只能在一个维度延伸,所以只能读取一行。所以每读入一行,就要输出line的内容。但是这样的话,每次进入while循环中,不应该先清空line中的内容吗?
事实上,每次getline函数执行时,会直接覆盖line原有的内容。比如第一次getline把第一行内容读入line,下一次getline执行时,就直接把第一行的内容覆盖掉了。就好比数组中将某个区间内的元素往后移动,直接覆盖。此外,getline函数每次调用时会从指定的流对象(这里是inFile)中读取一行数据到string类型的变量(这里是line)中,并且会自动忽略换行符。当到达文件末尾时,getline函数会返回false.而且,getline还可以指定分隔符:getline(istream&is,string&str,char ch);这个重载版本会读到指定的分隔符ch为止,而不是默认的换行符。
再提问:getline(istream&is,string& str)与getline(ifstream&is,string& str)有区别吗?
实际上,ifstream是从istream派生而来的。这意味着所有ifstream对象都可以当作istream对象来使用。所以是没有区别的。如果是普通的istream对象,我们就可以在控制台中输入内容,然后我们输入的内容就会被写入我们指定的字符串当中。如果是ifstream对象,我们就可以将文件中的内容提取出来到指定的字符串中。前者是“写+读”,后者是“读”。这么设计的好处是,getline函数不仅能从文件中读取数据,还能从标准输入读取数据,将控制台输入的内容读入字符串。这种多态性使得代码更加灵活和可复用。虽然cin更多涉及用户输入(写+读),ifstream侧重从文件读,但本质上都是从输入流中获取数据。统一使用istream&参数,getline函数可以无缝适配不同类型的输入源。