• C/C++ 文件读写


     

    •前言

      第一次接触文件读写是在大一的C语言教材中,当时哼哧吧唧的学的贼费劲,虽然最后也学会了,但好像没怎么用过。

      在后来,就是在OJ上刷题的时候,编写的代码有时候连样例都不能通过;

      这个时候就需要各种修改,然后各种输入样例,调试起来显得很费力,差不多这个时候,才正式开始使用文件读写。

      体验真的棒~~

    •C中的文件读写-freopen

    函数简介

      freopen  是被包含于 C标准库头文件  stdio.h  中的一个函数,用于重定向输入输出流。

      该函数可以在不改变代码原貌的情况下改变输入输出环境,但使用时应当保证流是可靠的。

    函数声明

     *FILE freopen(const char* _FileName, const char* _Mode, FILE* _Stream ); 

    • _FileName:需要重定向的文件名或文件路径
    • _Mode:代表文件访问权限的字符串
      • "r" 表示 只读访问
      • "w" 表示 只写访问
      • "a" 表示 追加写入
    • _Stream:需要被重定向的文件流
      • stdin:表示输入重定向(从指定文件中读取数据到程序中)
      • stdout:表示输出重定向(将程序中输出的数据输入到指定文件中)
    • 返回值:如果成功,则返回指向该输出流的文件指针,否则返回为NULL

    测试输出重定向(写文件)

      新建一个项目,并命名为文件读写;

      在该项目中创建一个  C中的文件读写.c  文件,并添加如下代码:

    复制代码
    #include<stdio.h>
    #define FILENAME "FILEC.txt"//文件名
    
    void write()
    {
        freopen(FILENAME, "w", stdout);
    
        printf("测试向FILEC.txt中写文件\n");
    }
    int main()
    {
        write();
    
        return 0;
    }
    复制代码

      运行该代码,你会发现,在项目文件读写的文件夹下多出一个  FILEC.txt 的文件,打开该文件,你会惊奇的发现,该文件的内容就是你在程序中通过 printf 输出的语句。

      通过代码可以看出,freopen 函数只出现在了  write() 函数中,那么如果在主函数中输出 "Hello World",会输出到哪里呢?

      让我们通过代码来测试一下。

    复制代码
    void write()
    {
        freopen(FILENAME, "w", stdout);
    
        printf("测试向FILEC.txt中写文件\n");
    }
    int main()
    {
        printf("TEST1 : Hello World\n");
        write();
        printf("TEST2 : Hello World\n");
    
        return 0;
    }
    复制代码

      运行该代码,你会发现,在控制台只输出了 "TEST1 : Hello World":

      少的那一句呢?

      莫非是输出到 FILEC.txt  中了,让我们一探究竟。

      果然在这里,通过这个测试,就能发现,在语句  freopen(FILENAME, "w", stdout); 调用后,所有的输出语句都写到了  FILEC.txt 中。

      C 语言中提供了文件读写的关闭语句  fclose(stdout) ,那可不可以通过该语句实现随开随关呢?

      让我们尝试在  write() 中使用该语句。

    复制代码
    void write()
    {
        freopen(FILENAME, "w", stdout);
    
        printf("测试向FILEC.txt中写文件\n");
    
        fclose(stdout);
    }
    int main()
    {
        printf("TEST1 : Hello World\n");
        write();
        printf("TEST2 : Hello World\n");
    
        return 0;
    }
    复制代码

      让我们来运行一下修改后的程序。

    运行结果

      在 VS2022 上,直接报错了:

      而在 CodeBlocks 中测试,成功运行了:

      但是, FILEC.txt 文件中却丢失了  printf("TEST2 : Hello World\n"); 语句的输出结果:

      所以,通过测试可知,并不能通过  fclose(stdout); 语句实现随开随关 ,正确的写法应该是:

    复制代码
    #include<stdio.h>
    #define FILENAME "FILEC.txt"//文件名
    
    void write()
    {
        freopen(FILENAME, "w", stdout);
    
        printf("测试向FILEC.txt中写文件\n");
    }
    int main()
    {
        printf("TEST1 : Hello World\n");
    
        write();
    
        printf("TEST2 : Hello World\n");
    
        fclose(stdout);//放置到程序结尾处
        return 0;
    }
    复制代码

    测试输入重定向(读文件)

      在程序所在目录下新建一个 Input.txt 文件,并输入如下信息:

      运行如下代码:

    复制代码
    #include<stdio.h>
    #define FILENAME "Input.txt"
    
    int main()
    {
        freopen(FILENAME,"r",stdin);//读文件
        
        char s[100];
        while (scanf("%s", s) != EOF)
            puts(s);
        
        return 0;
    }
    复制代码

      运行该程序,你会发现,并不需要输入任何数据:

      控制台输出的内容刚好是  Input.txt  中的内容。

    • scanf("%s", s) != EOF 表示的是读取到文件结尾
    • FILENAME 也可以换成 Input.txt 的具体路径 

     E:\\Documents\\Visual Studio for C++\\文件读写\\文件读写\\Input.txt 

    • 其中,路径中的 "\\" 可以换成 '/',但不能是 '\'

      同理,我们也可以用  fclose(stdin); 来关闭该输入流,但同输出流一样,应该放到程序结尾出:

    复制代码
    #include<stdio.h>
    #define FILENAME "Input.txt"
    
    int main()
    {
        freopen(FILENAME,"r",stdin);//读文件
        
        char s[100];
        while (scanf("%s", s) != EOF)
            puts(s);
        
        fclose(stdin);//放到程序结尾处
        return 0;
    }
    复制代码

    •C++中的文件读写-fstream

    函数简介

      C++中对文件操作需要包含头文件  <fstream> (file stream,文件流)。

    • ofstream:写操作(output file stream)
    • ifstream: 读操作(input file stream)
    • fstream : 读写操作(file stream)

    写文件

    步骤

    • 创建流对象:ofstream ofs; 
    • 打开文件:ofs.open("文件名/文件路径",打开方式);
    • 写数据:ofs << "写入的数据"; (将 cout 改为 ofs)
    • 关闭文件:ofs.close(); 

    文件打开方式

    •  ios::out :为写文件而打开文件
    •  ios::app :追加方式写文件

      在代码所在的文件夹下新建一个  FILEC++.txt 文件,添加如下数据:

      并运行如下代码:

    复制代码
    #include<iostream>
    #include<fstream>//包含头文件
    using namespace std;
    #define FILENAME "FILEC++.txt"
    
    void write()
    {
        ofstream ofs;//创建流对象
        ofs.open(FILENAME, ios::out);//打开文件
    
        ofs << "测试向FILEC++.txt中写文件" << endl;//写数据
    
        ofs.close();//关闭文件
    }
    int main()
    {
        write();
    
        return 0;
    }
    复制代码

      打开  FILEC++.txt 查看文件内容变化。

      你会发现,通过  ios::out 方式打开文件,之前的内容被覆盖了。

      更改文件打开方式:

    复制代码
    void write()
    {
        ofstream ofs;//创建流对象
        ofs.open(FILENAME, ios::app);//打开文件
    
        ofs << "测试向FILEC++.txt中写文件-2.0" << endl;//写数据
    
        ofs.close();//关闭文件
    }
    
    复制代码

      查看  FILEC++.txt 中的内容:

      可以测试出, ios::app 是在原文件的基础上向后追加内容。

      由于是通过创建  ofs 来进行写文件操作,那么原本的输出语句就不会报错。

    复制代码
    #include<iostream>
    #include<fstream>//包含头文件
    using namespace std;
    #define FILENAME "FILEC++.txt"
    
    void write()
    {
        ofstream ofs;//创建流对象
        ofs.open(FILENAME, ios::out);//打开文件
    
        ofs << "测试向FILEC++.txt中写文件" << endl;//写数据
    
        ofs.close();//关闭文件
    }
    int main()
    {
        cout << "TEST1 : Hello World" << endl;
        write();
        cout << "TEST2 : Hello World" << endl;
        return 0;
    }
    复制代码

      运行结果:

       FILEC++.txt :

      可见,通过  ofstream 来进行写文件操作,并不会影响  cout 的输出。

    读文件

    步骤

    • 创建流对象: ifstream ifs; 
    • 打开文件: ifs.open("文件路径",打开方式); 
    • 判断文件是否打开成功: ifs.is_open() (成功打开返回 true,否则返回 false)
    • 读数据: ifs >> 变量1 >> 变量2 >> ...; (类比 cin)
    • 关闭文件: ifs.close(); 

    示例

      在当前代码所在文件夹下新建一个  Input.txt 的文件,并放入如下数据:

      分别代表:编号、姓名、年龄,并用 id , name , age 接受这三个数据。

    复制代码
    #include<iostream>
    #include<fstream>//包含头文件
    using namespace std;
    #define FILENAME "Input.txt"
    
    void read()
    {
        ifstream ifs;//创建流对象
        ifs.open(FILENAME, ios::in);//打开文件
    
        int id;
        string name;
        int age;
    
        if (!ifs.is_open())//判断文件是否打开成功
        {
            cout << "文件打开失败" << endl;
            return;
        }
    
        ifs >> id >> name >> age;//读数据,且 编号、姓名、年龄 要和文件中的数据保持一致
        cout << "编号\t姓名\t年龄" << endl;
        cout << id << "\t" << name << "\t" << age << endl;
    
        ifs.close();//关闭文件
    
        return;
    }
    int main()
    {
        read();
    
        return 0;
    }
    复制代码

      运行结果:

     


    __EOF__

  • 本文作者: MElephant
  • 本文链接: https://www.cnblogs.com/hyacinthLJP/p/16059338.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    DotNetCore环境离线CentOS安装
    从「纯野妆」到「降温妆」,解析小红书“热词爆款学”
    C++11之追踪返回类型
    Vue 03 数据绑定
    2022年华数杯C题插层熔喷非织造材料的性能控制研究
    java计算机毕业设计医院门诊预约系统源程序+mysql+系统+lw文档+远程调试
    聊聊ShardingSphere是怎么进行sql重写的
    使用接口根据关键词取视频列表详情
    云服务部署:AWS、Azure和GCP比较
    十七年运维老兵万字长文讲透优维低代码~
  • 原文地址:https://www.cnblogs.com/hyacinthLJP/p/16059338.html