• C++中的文件操作




    文件操作


    视频链接



    C++中的文件操作时基于面向对象的


    程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放

    通过文件可以将数据持久化

    C++中对文件操作需要包含头文件 < fstream >



    C++中文件类型分为两种:

    1. 文本文件 - 文件以文本的ASCII码形式存储在计算机中
    2. 二进制文件 - 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们


    操作文件的三大类(这些类都属于标准模板库):

    1. ofstream(output):写入文件操作
    2. ifstream(input): 读取数据操作
    3. fstream : 读写操作。一般使用这个类进行文本操作



    1 文本文件

    1.1 写文件

    写文件步骤如下:
    1. 包含头文件

      #include

    2. 创建流对象

      ofstream ofs;

    3. 打开文件

      ofs.open(“文件路径”,打开方式);
      文件路径可以直接写个文件名,因为如果不指定路径的话,他会默认在当前项目路径下。

    4. 写数据

      ofs << “写入的数据”;
      类似于cout<<“…”; cout就是往屏幕上输出,而ofs就是往文件里输出

    5. 关闭文件,这一步很重要而且容易遗漏

      ofs.close();



    文件打开方式:

    在这里插入图片描述



    #include
    using namespace std;
    #include
    // 1.包含头文件 fstream
    #include
    // 文本文件 写文件
    void test01() {
    	// 1.包含头文件
    	// 2.创建流对象
    	ofstream ofs;
    	// 3.指定打开的方式
    	//文件名为test.txt
    	ofs.open("test.txt", ios::out);
    	// 4.写内容
    	ofs << "姓名:张三" << endl << "年龄:19" << endl << "性别:男" << endl;
    	// 5.关闭文件
    	ofs.close();
    
    }
    int main() {
    	test01();
    	cin.get();
    	return 0;
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述



    在这里插入图片描述

    总结:

    • 文件操作必须包含头文件 fstream
    • 读文件可以利用 ofstream ,或者fstream类
    • 打开文件时候需要指定操作文件的路径,以及打开方式
    • 利用<<可以向文件中写数据
    • 操作完毕,要关闭文件




    1.2 读文件

    读文件与写文件步骤相似,但是读取方式相对于比较多

    读文件步骤如下:

    1. 包含头文件

      #include

    2. 创建流对象

      ifstream ifs;

    3. 打开文件并判断文件是否打开成功

      ifs.open(“文件路径”,打开方式);

    4. 读数据

      四种方式读取

    5. 关闭文件,记住别忘了要关闭文件

      ifs.close();



    判断文件是否打开成功(其实也就是判断有没有这个文件):

    if (!ifs.is_open())
    	{
    		cout << "文件打开失败" << endl;
    		return;
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    if_open()是系统自带的布尔类型函数,打开成功返回1
    打开失败返回0(这个函数是判断文件是否存在的)



    读取文件数据的四种方式
    按照喜好记前三个中的一个就行
    1. 第一种方式:把文件内容全部放在字符数组中
    //第一种方式
    	char buf[1024] = { 0 };//首先初始化字符数组
    	while (ifs >> buf)
    	//  ifs右移运算符,他会读取数据并放到buf数组中,当数据全部读完后,返回一个false,while循环也就结束了
    	{
    		cout << buf << endl;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7


    1. 第二种方式:使用ifs.getline()函数
      ifs.getline(char *str,count)中有两个参数;

    char *str:表示我们要把读取的数据放到哪个地方,一般是个数组
    count:所占的空间
    在这里插入图片描述



    //第二种
    	char buf[1024] = { 0 };
    	while (ifs.getline(buf,sizeof(buf)))
    	{
    		cout << buf << endl;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6


    1. 第三种方式:把内容放到string字符串中
      包含头文件include
      然后使用函数getline(输入流对象,准备好的字符串)
    //第三种
    	string buf;
    	while (getline(ifs, buf))
    	{
            cout << buf << endl;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6


    1. 不太推荐的第四种方式:他会将文件中的所有数据一个一个地读出来,放到字符C里边。效率太差

    ifs.get()每次只读一个字符。EOF代表末尾的意思

    // 第四种
    	char c;
    	while ((c = ifs.get()) != EOF)
    	{
    		cout << c;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6



    综合
    #include
    using namespace std;
    //1. 包含头文件
    #include
    #include
    
    
    
    void test01()
    {   // 2. 创建流对象  
    	ifstream ifs;
    
    
    	//3. 打开文件并判断文件是否打开成功
    	ifs.open("test.txt", ios::in);
    
    
    	if (!ifs.is_open())
    	{
    		cout << "文件打开失败" << endl;
    		return;
    	}
    
    	// 4. 读数据
    	// 四种方式
    
    	//第一种方式
    	//char buf[1024] = { 0 };
    	//while (ifs >> buf)
    	//{
    	//	cout << buf << endl;
    	//}
    	
    
    
    
    
    
    
    	//第二种
    	//char buf[1024] = { 0 };
    	//while (ifs.getline(buf,sizeof(buf)))
    	//{
    	//	cout << buf << endl;
    	//}
    
    	//第三种
    	string buf;
    	while (getline(ifs, buf))
    	{
            cout << buf << endl;
    	}
    
    
    	// 第四种
    	//char c;
    	//while ((c = ifs.get()) != EOF)
    	//{
    		//cout << c;
    	//}
    
    
    	// 5. 关闭文件
    	ifs.close();
    
    
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    在这里插入图片描述






    2 二进制文件(不仅可以操作内置数据类型还可以操作自定义数据类型)

    以二进制的方式对文件进行读写操作

    注意打开方式要指定为 ios::binary



    2.1 写文件

    二进制方式写文件主要利用流对象调用成员函数write

    函数原型 :ostream& write(const char * buffer,int len);

    在这里插入图片描述





    参数解释:参数一:字符指针常量buffer(也可以理解为就是一段地址(指针就是地址),不过要把它强制转换成const char * ) 。 buffer指向内存中一段存储空间。len是读写的字节数

    数组名就可以直接作为参数一,当传数组给一个函数时,数组类型自动转换为指针类型,传的实际是数组元素首地址。

    建议看的文章1:将地址强制转换为指针

    建议看的文章2指针的强制类型转换



    注意:对文件操作时,字符串最好使用C语言风格的字符串(也就是字符数组)因为wirte()和read函数()都包含参数char *,用string会引发错误

    在这里插入图片描述



    #include
    using namespace std;
    
    #include 
    #include 
    
    class Person
    {
    public:
    	char m_Name[64];
    	int m_Age;
    };
    
    //二进制文件  写文件
    void test01()
    {
    	//1、包含头文件
    
    	
    
    	//2、创建输出流对象
    	ofstream ofs("person.txt", ios::out | ios::binary|ios::trunc);
    
    	//3、打开文件
    	//ofs.open("person.txt", ios::out | ios::binary);
    
    	int a = 55;
    	int d[20];
    	for (int i = 0; i < 20; i++) {
    
    		d[i] = i;
    	 }
    	Person p = { "张三"  , 18 };
    
    	char c[15] = { "Hello,World!" };
    
    	//4、写文件
    	ofs.write((const char*)&a, sizeof(a));
    	ofs.write((const char*)d, sizeof(c));
    	ofs.write((const char*)&p, sizeof(p));
    	ofs.write((const char*)c, sizeof(c));
    	//5、关闭文件
    	ofs.close();
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    在这里插入图片描述



    二进制文件打开是乱码
    在这里插入图片描述




    2.2 读文件

    二进制方式读文件主要利用流对象调用成员函数read

    函数原型:istream& read(char *buffer,int len);

    参数解释:参数一:字符指针buffer(也可以理解为就是一段地址(指针就是地址),不过要把它强制转换成 char * ) 。它指向内存中一段存储空间。len是读写的字节数

    数组名可以直接作为参数一,当传数组给一个函数时,数组类型自动转换为指针类型,传的实际是数组元素首地址。



    步骤
    1. 包含头文件
    2. 创建流对象
    3. 打开文件并判断文件是否打开成功
    4. 将二进制数据转换为可读数据
    5. 打印转换后的可读数据
    6. 关闭文件
    
    
    #include
    using namespace std;
    // 1.包含头文件
    #include 
    #include 
    
    class Person
    {
    public:
    	char m_Name[64];
    	int m_Age;
    };
    
    void test01()
    {
    
    	 // 2.创建流对象的同时打开文件
    	ifstream ifs("person.txt", ios::in | ios::binary);
    
    	// 3.判断文件是否打开成功
    	if (!ifs.is_open())
    	{
    		cout << "文件打开失败" << endl;
    	}
    
    	Person p;
    	
    	// 4.将二进制数据转换为可读数据
    	// 这一步不能将数据读出到屏幕上,这一步的作用只是把二进制数据转换为可读数据
    
    	
    
    	
    	int d;
    	int z[20];
    	char c[15];
    	ifs.read((char*)&d, sizeof(d));
    	ifs.read((char*)z, sizeof(z));
    	ifs.read((char*)&p, sizeof(p));
    	ifs.read((char*)c, sizeof(c));
    	
    
    	// 5.打印转换后的可读数据
    	// 用cout即可读出数据
    	cout << "d=" << d << endl;
    	cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
    	
    	for (int i = 0; i < 20; i++) {
    		cout << z[i] << endl;
    	}
    	for (int i = 0; i < 15; i++) {
    		cout << c[i];
    	}
    	cout << endl;
    	// 6.关闭文件
    	ifs.close();
    
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    在这里插入图片描述





    注意事项:

    1. 把什么数据类型写入文件,查看文件时就要用相应的数据类型来接受。

    比如用write函数写入一个整形数组:

      
    	int c[20];
    	
    ofs.write((const char*)&c, sizeof(c));
    
    • 1
    • 2
    • 3
    • 4

    那么read函数接受时也应用整形数组来接受:

    int z[20];
    ifs.read((char*)z, sizeof(z));
    
    • 1
    • 2


    1. 用write函数按某一顺序写入了多个数据类型时,read函数查看时也应与写入时的顺序一样

    比如按下列顺序用write函数写入了以下四个数据类型:

        int a = 55;
    	int d[20];
    	Person p = { "张三"  , 18 };
    
    	char c[15] = { "Hello,World!" };
    
    	//4、按下列顺序写入文件
    	ofs.write((const char*)&a, sizeof(a));
    	ofs.write((const char*)d, sizeof(c));
    	ofs.write((const char*)&p, sizeof(p));
    	ofs.write((const char*)c, sizeof(c));
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14


    read函数查看时也得与写入时的顺序相同:

        int d;
    	int z[20];
    	char c1[15];
    	Person p1;
    // 注意各个read函数的顺序
    	ifs.read((char*)&d, sizeof(d));
    	ifs.read((char*)z, sizeof(z));
    	ifs.read((char*)&p1, sizeof(p1));
    	ifs.read((char*)c1, sizeof(c1));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9


    不能写成下面这样:

        int d;
    	int z[20];
    	char c1[15];
    	Person p1;
        ifs.read((char*)&d, sizeof(d));
    	ifs.read((char*)c1, sizeof(c1));
    	ifs.read((char*)z, sizeof(z));
    	ifs.read((char*)&p1, sizeof(p1));
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    数据包伪造替换、会话劫持、https劫持之探索和测试
    IntelliJ IDEA 配置启动SprintBoot项目
    PyTorch主要组成模块 | hook函数 | 正则化weight decay与Dropout | 标准化
    ResNet网络详解及其PyTorch实现
    Linux 指令心法(十)`head` 显示文本文件的开头部分
    pdf怎么转换成jpg或png格式的图片?
    Vue项目中 vantUI中tab标签栏下划线位置异常,指定下标但是显示还是默认下标。解决方案
    第二证券:“零容忍”执法 资本市场加大防假打假力度
    C#替换字符串中花括号的参数
    Scala第十六章节
  • 原文地址:https://blog.csdn.net/weixin_53213086/article/details/126894865