文件操作是每门语言的必学项目,C++中同样如此,且C++中通过流(stream)这一形式进行输入输出、文件读写的控制。因此,对流的概念把握是必要的。
何为流?
国外很多视频网站上常常能看到流(stream)这一字眼,比如直播就是live stream。流其实是对数据传输的一种形象表述。看视频的本质不过是视频数据流。文件读写同样也是一种数据传输,故称为文件流。
C++中流类型的关系

从图中可以看出,流类型包括两大类,输入输出流(iostream)和文件流(fstream),文件流则继承自输入输出流。
文件打开
在对文件操作之前,首先需要考虑的是,对这个文件是读还是写?如果只是读的话,用ifstream
就可以了;如果只是写,用ofstream
就够了;需要兼顾读写时,则用fstream
。最好进行区分,方便重读代码时理解。
打开文件之前还需要了解,打开文件的模式,常用的有如下几种:
模式 | 适用对象 | 作用 |
---|---|---|
ios::in | ifstream fstream |
读取数据 |
ios::out | ofstream fstream |
写入数据,如果文件原来就存在,则打开时清除原来的内容。 |
ios::binary | fstream ifstream ofstream |
以二进制方式打开文件。若不指定此模式,则以文本模式打开 |
ios::app | ofstream fstream |
打开文件,并在其尾部写入 |
ios::trunc | ofstream fstream |
单独使用和ios::out相同 |
ios::in|ios::out|ios::trunc | fstream | 打开文件,既可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容;如果文件不存在,则新建该文件。 |
打开文件有两种语法,一是用open
函数打开,二是利用默认的构造函数,没什么差别。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream inFile;
inFile.open("c:\\test.txt", ios::in);
ifstream inFile("c:\\test.txt", ios::in); //同上
ofstream oFile;
oFile.open("test1.txt", ios::out);
ofstream oFile("test1.txt", ios::out);//同上
fstream ioFile;
ioFile.open("..\\test3.txt", ios::out | ios::in | ios::trunc);
fstream ioFile("..\\test3.txt", ios::out | ios::in | ios::trunc);//同上
}
文件读写
读文件
- 空格或换行符分隔文件
1 234 9 45
6 879
对于这样的文件(test.txt),可用箭头符读取,下面例子演示将文件中数据保存到数组中。
const int max_num = 1000;
int a[max_num];
int pos=0;
ifstream srcFile("test.txt",ios::in); //以文本模式打开
int x;
while(srcFile >> x)
a[pos++]=x;
srcFile.close(); //文件用完后记得关闭
- 逗号分隔文件(csv文件)
3,4,5
6,7,8
9,10,11
现在很多数据采用的是这种格式存储,对于这种文件,需要利用到sstream类,
#include <fstream>
#include <sstream>
...
ifstream ifile("data.csv", ios::in);
string line;
while (getline(ifile, line)) //获取一行
{
// cout << line << endl;
istringstream sin(line);
vector<int> temp;
string tmp;
while (getline(sin, tmp, ',')) //获取一个数据
{
temp.push_back(stoi(tmp)); //存到temp中
}
}
- 用read成员函数读数据
这对固定格式的数据比较适合,一般用于二进制文件的读取,因其每个项目的长度是固定的。
//student.dat 二进制存储以下数据
Tom 60
Jack 80
Jane 40
#include <iostream>
#include <fstream>
using namespace std;
class CStudent
{
public:
char szName[20];
int age;
};
int main()
{
CStudent s;
ifstream inFile("students.dat",ios::in|ios::binary); //二进制读方式打开
if(!inFile) {
cout << "error" <<endl;
return 0;
}
while(inFile.read((char *)&s, sizeof(s))) { //一直读到文件结束
int readedBytes = inFile.gcount(); //看刚才读了多少字节
cout << s.szName << " " << s.age << endl;
}
inFile.close();
return 0;
}
写文件
写文件一般像打印到命令行一样,给定格式用箭头符写入即可
ofstream ofile;
try
{
ofile.open("out.csv", ios::out);
for (size_t i = 0; i < N; i++)
for (size_t j = K; j < T + K; j++)
ofile << i << ',' << j - K << ',' << s[i][j] << endl;
}
catch (const std::exception &e)
{
std::cout << "file write error." << std::endl;
std::cerr << e.what() << '\n';
}
ofile.close();
高级用法
有时打开一个文件后,需要跳转到某一个特定位置开始读写,这时需要用到seekg(seekp)
和tellg(tellp)
函数...
网友评论