文件操作
-
- 文件的打开方式
- [ios::app(append)和 ios::ate(at end)](#ios::app(append)和 ios::ate(at end))
-
程序运行时产生的数据都属于临时数据,一旦程序运行完毕,就会释放,要想保存,可以通过将其写入文件。
-
同时,程序中使用的一些数据也可以通过读文件的方式应用于程序中。
文件类型
- 文件的读写方式有两种,文本文件和二进制文件。
- 计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。
文本文件
- 文本文件是基于字符编码的文件,常见的编码有ASCII编码,UNICODE编码等等。
二进制文件
- 二进制文件有特定的编码方式,用户一般不能直接读懂。
- 二进制文件是基于值编码的文件,你可以根据具体应用,指定某个值是什么意思(这样一个过程,可以看作是自定义编码。
- 二进制文件可看成是变长编码的,因为是值编码嘛,多少个比特代表一个值,完全由你决定。大家可能对BMP文件比较熟悉,就拿它举例子吧,其头部是较为固定长度的文件头信息,前2字节用来记录文件为BMP格式,接下来的8个字节用来记录文件长度,再接下来的4字节用来记录bmp文件头的长度。
文件操作的三大类
需要包含头文件,fstream, f:file
- ofstream, o: out, 代码往外吐数据,即写到文件去。
- ifstream, i: in, 入向代码,从文件读到代码中。
- fstream,in,out均包括。
文件的打开方式
打开方式 | 适用对象 | 说明 |
---|---|---|
ios::in | ifstream,fstream | 打开文件用于读取数据,如果文件不存在,则打开出错 |
ios::out | ofstream,fstream | 打开文件用于写入数据。如果文件不存在,则新建该文件;如果文件原来就存在,则打开时清除原来的内容 |
ios::app | ofstream,fstream | 打开文件,用于在其尾部添加数据。如果文件不存在,则新建该文件,每次的写入操作都会在后面追加 |
ios::ate | ofstream,fstream | 打开一个已有的文件,并将文件指针指向文件末尾。如果文件不存在,则打开出错 |
ios:: trunc | ofstream | 打开文件时会清空内部存储的所有数据,相当于先删除原有文件,再重新建立一个文件 |
ios::binary | ifstream,ofstream,fstream | 以二进制方式打开文件。若不指定此模式,则以文本模式打开 |
ios::in | ios::out | ios::trunc | fstream | 打开文件,既可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容;如果文件不存在,则新建该文件 |
ios::app(append)和 ios::ate(at end)
-
每个文件都有一个位置指针,指向将要读写的下一个字节,打开文件时,默认的位置指针指向文件的开始;打开方式ate(表示at-end)和app(表示追加)能将位置指针定位到文件尾。
-
如果以追加方式打开文件,所有向文件的输出从当前文件的尾部开始进行,不必重新定位。即使你修改文件位置指针不指向文件尾部,也不会将输出写到那里。
以at-end方式打开文件时,文件起始位置指向文件尾部,但你可以修改位置指针指向其它位置,输出则写到指针指向的位置。
-
在实际应用中,如果需要在多个线程或进程间安全地追加数据到文件中,而不希望数据被覆盖或混淆,那么ios::app模式是最佳选择。
-
而如果需要在打开文件时就确定写指针的位置,或者需要清空文件内容然后重新写入,那么使用ios::ate模式可能更为合适, 然而,值得注意的是,如果只使用ios::ate模式而不配合ios::in或ios::out模式,将会清空原文件的内容。
-
当使用ios::app模式时,如果打开的文件不存在,系统将自动创建该文件。
-
而当使用ios::ate模式时,如果打开的文件不存在,系统将无法打开文件,报错。
写文件
写文件文件步骤
- 包含头文件, #include <fstream>
- 创建流对象,通过流对象,可以与文件打交道,ofstream ofs
- 打开文件,参数有文件的路径,打开方式等,ofs.open(文件路径,打开方式), 也可以创建流对象和打开合并为一个ofstream ofs(文件路径,打开方式)
- 向文件写入内容 ofs << 写入的数据
- 关闭文件, ofs.close()
读文件文件步骤
- 包含头文件, #include <fstream>
- 创建流对象,通过流对象,可以与文件打交道,ifstream ofs
- 打开文件,参数有文件的路径,打开方式等,ofs.open(文件路径,打开方式), 也可以创建流对象和打开合并为一个ifstream ifs(文件路径,打开方式)
- 从文件读取内容
-- 方法1,创建字符数组接收读取文件的内容,使用ifs >> 字符数组,while (ifs >> buf)
-- 方法2,创建字符数组接收读取文件的内容,使用ifs.getline(字符数组,sizeof(字符数组)),(ifs.getline(buf, sizeof(buf)))
-- 方法3,创建字符串接收读取文件的内容,使用string的全局函数getline(流对象,字符串变量),while (getline(ifs, buf))
-- 方法4,创建字符接收读取文件的内容,使用ifs.get(),while(char_data = ifs.get())!=EOF) - 关闭文件, ofs.close()
cpp
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
void main()
{
ofstream ofs("d:/student.txt", ios::ate); // 创建流对象,并打开
ofs << "张三,10" << endl << "李四,20" << endl << "王五,30" << endl; // 写入文件
ofs.close();
ifstream ifs("d:/student.txt", ios::in); // 创建流对象,写读取方式打开文件
if (!ifs.is_open()) // 判断文件是否打开成功
return;
// 方法1,使用ifs >> buf的方式,用字符数组来接收文件中的数据
//char buf[100] = { 0 }; // 创建字符数组用于存放读取的数据
//while (ifs >> buf) // ifs >> buf, 将文件中的数据依次放入buf中,当读完后,此条件不满足
//{
// cout << buf << endl;
//}
// 方法2,使用流对象的方法getline(char* 接收数据的字符数组的地址,sizeof(要接收数据的字符数组))
//char buf[100] = { 0 }; // 创建字符数组,用于存放读取的数据
//while (ifs.getline(buf, sizeof(buf))) // 使用对象方法getline将文件中的数据放入buf中,当读完后,此条件不满足
//{
// cout << buf << endl;
//}
//ifs.close();
//system("pause");
// 方法3,使用全局函数getline
//string buf;
//while (getline(ifs, buf)) // 使用全局方法getline(输入流对象,接收数据的字符串)#include <string>需要包含,将文件中的数据放入buf中,当读完后,此条件不满足
//{
// cout << buf << endl;
//}
// 方法4,逐个字符读取, 这种方式的效率比较低
char char_data;
while ((char_data = ifs.get())!=EOF) // EOF: end of files
{
cout << char_data;
}
}
二进制文件读写
写一般数据
cpp
#include <fstream> // 包含头文件
#include <iostream>
using namespace std;
void main()
{
char str1[30] = "张三,10\n李四,20";
char str2[30] = {0};
ofstream ofs("d:/person.txt", ios::out | ios::binary); // 创建输出流对象,打开文件,二进制写入方式ios::binary
if (!ofs)
{
cout << "创建文件失败" << endl;
return;
}
ofs.write((const char*)str1, sizeof(str1)); //write以char *的方式进行写出,做一个转化,write(要写入的数据地址,数据长度)
ofs.close(); // 关闭文件
ifstream ifs("d:/person.txt", ios::in | ios::binary);
if (!ifs)
{
cout << "读取文件失败" << endl;
return;
}
ifs.read((char*)str2, sizeof(str2)); // read(char* 读取数据的接收地址,接收数据的字符数组长度)
cout << str2 << endl;
ifs.close(); // 关闭文件
system("pause");
}
写特殊数据
cpp
#include <fstream>
#include <iostream>
using namespace std;
class Person
{
public:
Person(string name, int age) : m_name(name), m_age(age) {} // 初始化列表
string m_name;
int m_age;
};
void main()
{
Person p1("张三", 10);
Person p2("1", 0);
ofstream ofs("d:/person.txt", ios::out | ios::binary);
ofs.write((const char*)&p1, sizeof(p1));
ofs.close();
ifstream ifs("d:/person.txt", ios::in | ios::binary);
ifs.read((char*)&p2, sizeof(p2));
if (!ifs)
{
cout << "读取文件失败" << endl;
return;
}
cout << p2.m_name << ", " << p2.m_age << endl;
ifs.close();
system("pause");
}