0 文件I/O操作
程序运行时产生的数据均为临时数据,临时数据会在程序执行完毕时被释放。可通过文件持久化数据。
注:C++中操作文件时,需包含文件流相关的头文件
<fstream>
。
文件分类:
(1)文本文件
:文件以文本的ASCII码形式存储;
(2)二进制文件
:文件以文本的二进制形式存储,用户一般无法直接阅读。
文件操作的类:
(1)ofstream
:写操作(Output File Stream)
(2)ifstream
:读操作(Input File Stream)
(3)fstream
:读/写操作(File Stream)
1 文本文件
1.1 写文件
写文件的步骤:
(1)包含头文件:#include <fstream>
(2)创建输出流对象:ofstream ofs;
(创建文件输出流对象)
(3)以指定路径和方式打开文件:ofs.open("文件路径", 打开方式);
(4)通过文件输出流对象和左移运算符<<
写数据:ofs << "写入数据";
(5)关闭文件:ofs.close();
注:通过文件输出流类
ofstream
的构造函数,在创建文件输出流对象时指定文件的路径及打开方式,从而省略ofs.open("文件路径", 打开方式);
函数:
ofstream ofs("文件路径", 打开方式);
文件打开方式:
打开方式 | 解释 |
---|---|
ios::in | 读文件 |
ios::out | 写文件 |
ios::ate | 打开的初始位置:文件尾 |
ios::app | 以追加方式写文件(追加写) |
ios::trunc | 若文件已存在,则先删除,再创建 |
ios::binary | 二进制方式 |
注:文件打开方式可通过位或操作符
|
组合使用。
例:以二进制方式写文件:ios::binary | ios:: out
。
文本文件-写操作总结:
(1)文件操作必须包含头文件<fstream>
;
(2)写文件可使用ofstream
或fstream
类;
(3)打开文件时,需指定文件路径与打开方式;
(4)可通过文件输出流对象和左移运算符<<
向文件写数据;
(5)操作完毕后,需要关闭文件。
示例:文本文件-写操作
#include <iostream>
using namespace std;
#include <fstream> //1.包含文件流相关的头文件
void writeTextFile() {
//2.创建文件输出流对象
ofstream ofs;
//3.以指定方式打开
ofs.open("test.txt",ios::out);
//4.写内容
ofs << "姓名:Tom" << endl;
ofs << "时间:2021年2月14日" << endl;
//5.关闭文件流对象
ofs.close();
}
int main() {
writeTextFile();
return 0;
}
1.2 读文件
读文件的步骤:
(1)包含头文件:#include <fstream>
(2)创建输入流对象:ifstream ifs;
(创建文件输入流对象)
(3)以指定路径和方式打开文件,并判断文件是否打开成功:
打开文件:ifs.open("文件路径", 打开方式);
判断文件是否打开成功:ifs.is_open()
(4)通过文件输入流对象,以4种方式读数据:
①字符数组和右移运算符>>
char buffer[1024] = {0}; //初始化字符数组
while(ifs >> buffer){
cout << buffer << endl;
}
②字符数组和ifstream类的成员函数ifstream& getline(char *_Str, std::streamsize _Count)
ifstream::getline(字符数组缓冲区, 缓冲区大小)
char buffer[1024] = { 0 }; //初始化字符数组
while (ifs.getline(buffer, sizeof(buffer))) {
cout << buffer << endl;
}
③字符串和全局函数getline(istream &_istr, string &_str)
getline(输入流对象, 字符串)
string str;
while(getline(ifs, str)){
cout << str << endl;
}
④逐字符读取、ifstream类的成员函数get()
和文件结束符EOF
(end of file)【不建议】
注:逐字符读取方式的效率较低,不建议使用。
char ch;
while ((ch = ifs.get()) != EOF) {
cout << ch;
}
(5)关闭文件:ifs.close();
判断文本文件内容是否为空(文件存在):
读取文本文件的1个字符,判断该字符是否为EOF标志。
(1)创建文件输入流对象:ifstream ifs;
(2)读取文本文件的1个字符:char ch;
ifs >> ch;
或ch = ifs.get();
(3)判断当前读取的字符,是否已达文件末尾(即文件结束符EOF
):
①使用文件输入流类的成员函数bool ifstream::eof();
;
②判断当前字符是否为文件结束符EOF
。
示例:判断文本文件内容是否为空
//方式1:文件输入流对象调用成员函数ifs.eof()
ifstream ifs(FILENAME, ios::in);
char ch;
ifs >> ch;
if(ifs.eof()){
cout << "文本文件内容为空..." << endl;
}
//方式2:判断当前字符是否为EOF文件结束符
ifstream ifs(FILENAME, ios::in);
char ch;
if((ch = ifs.get()) == EOF){
cout << "文本文件内容为空..." << endl;
}
文本文件-读操作总结:
(1)文件操作必须包含头文件<fstream>
;
(2)写文件可使用ifstream
或fstream
类;
(3)打开文件后,应使用ifstream类的is_open()
函数可以判断文件是否打开成功;
(4)操作完毕后,需要关闭文件。
示例:文本文件-读操作
#include <iostream>
using namespace std;
#include <fstream> //1.包含文件流相关的头文件
#include <string>
void readTextFile() {
//2.创建文件输入流对象
ifstream ifs;
//3.打开文件,并判断是否打开成功
ifs.open("test.txt", ios::in);
if (!ifs.is_open()) {
cout << "文件打开失败" << endl;
return;
}
//4.读数据
//第1种:字符数组和右移运算符>>
//char buffer[1024] = { 0 }; //初始化字符数组
//while (ifs >> buffer) {
// cout << buffer << endl;
//}
//第2种:字符数组和istream类成员函数getline()
//char buffer[1024] = { 0 }; //初始化字符数组
//while (ifs.getline(buffer, sizeof(buffer))) {
// cout << buffer << endl;
//}
//第3种:字符串和全局函数getline()
string str;
while(getline(ifs, str)){
cout << str << endl;
}
//第4种:按字符读取和EOF文件尾标志(end of file)【不建议】
//char ch;
//while ((ch = ifs.get()) != EOF) {
// cout << ch;
//}
//5.关闭文件
ifs.close();
}
int main() {
readTextFile();
return 0;
}
2 二进制文件
以二进制的方式对文件进行读写操作,open()函数
中的打开方式需额外使用ios::binary
。
2.1 写文件
二进制方式的写文件,通过文件输出流对象ofstream ofs;
调用成员函数write()
。
函数原型 :ostream& write(const char* buffer, int len);
参数解释:字符指针buffer
指向的内存地址;len
为读写的字节数。
注1:以二进制方式写文件时,支持写入自定义数据类型,需将自定义数据类型对象的地址(如
Object *
)强转为const char *
类型。
例:ofs.write((const char*) &obj, sizeof(obj));
注2:二进制写操作的文件,内容可能显示为乱码,需使用二进制的读操作解析。
注3:通过文件输出流类ofstream
的构造函数,在创建文件输出流对象时指定文件的路径及打开方式,从而省略ofs.open("文件路径", 打开方式);
函数:
ofstream ofs("文件路径", 打开方式);
示例:二进制方式写入自定义数据类型
#include <iostream>
using namespace std;
#include <fstream> //1.包含文件流相关的头文件
//自定义数据类型
class Student{
public:
char name[32];
int score;
};
int main() {
/*
//2.创建文件输出流对象
ofstream ofs;
//3.以二进制方式打开文件,并执行写操作
ofs.open("student.txt", ios::binary | ios::out);
*/
//简化写法
/* 通过输出流类ofstream的构造函数,创建对象时指定文件路径及打开方式 */
ofstream ofs("student.txt", ios::binary | ios::out);
//4.写文件
Student stu = {"Tom", 99 };
//将自定义的数据类型指针,强转为const char*
ofs.write((const char*)&stu, sizeof(stu));
//5.关闭文件
ofs.close();
return 0;
}
2.2 读文件
二进制方式的读文件,通过文件输入流对象ifstream ifs;
调用成员函数read()
。
函数原型 :istream& read(char* buffer, int len);
参数解释:字符指针buffer
指向的内存地址;len
为读写的字节数。
注1:以二进制方式读文件时,支持读取自定义数据类型,需将自定义数据类型对象的地址(如
Object *
)强转为char *
类型。
例:ifs.read((char*) &obj, sizeof(obj));
注2:打开文件后,应使用ifstream类的is_open()
函数可以判断文件是否打开成功。
示例:二进制方式读取自定义数据类型
#include <iostream>
using namespace std;
#include <fstream> //1.包含文件流相关的头文件
//自定义数据类型
class Student {
public:
char name[32];
int score;
};
int main() {
/*
//2.创建输入流对象
ifstream ifs;
//3.打开文件并判断是否打开成功
ifs.open("student.txt", ios::binary | ios::in);
*/
//简化写法
/* 通过输出流类ofstream的构造函数,创建对象时指定文件路径及打开方式 */
ifstream ifs("student.txt", ios::binary | ios::in);
if (!ifs.is_open()) {
cout << "文件打开失败..." << endl;
return 0;
}
//4.读文件
Student stu;
ifs.read((char*)&stu, sizeof(stu));
cout << "姓名:" << stu.name << endl;
cout << "成绩:" << stu.score << endl;
//5.关闭文件
ifs.close();
return 0;
}