• C++文件输入和输出


    1.引入头文件fstream
    fstream头文件定义了用于文件输入的类ifstream和文件输出的类ofstream

    2.写文件
    1)创建一个ofstream对象来管理输出流
    2)将该对象与文件关联起来
    3)使用cout方式使用该对象,唯一区别是输出将进入文件,而不是屏幕。
    4)关闭到文件的连接
    示例如下:

    ofstream fout;
    fout.open("test.txt");
    fout<<"write something";
    fout.close();

    创建对象和关联文件可使用构造函数合并到一步,以上代码等价于:

    ofstream fout("test.txt");
    fout<<"write something";
    fout.close();

    3.读文件
    1)创建一个ifstream对象来管理输入流
    2)将该对象与文件关联起来
    3)使用ifstream的方法读文件
    4)关闭到文件的连接
    示例如下:

    ifstream fin("test.txt");
    char ch;
    fin>>ch;//从文件中读取一个字符
    char buf[80];
    fin>>buf;//从文件中读取一个单词
    fin.getline(buf,80);//从文件中读取一行
    string line;
    getline(fin,line);//读取一行转换成字符串
    fin.close();

    4.读写缓冲区
    fstream流管理对象在使用cout或cin方式,读或写时,是通过缓冲区和文件进行交互的
    而不是逐字节读取或写入文件的。

    关于close()函数,当流对象过期(如程序终止)时,到文件的连接自动关闭,
    也可使用cose()显示关闭该连接。连接关闭后,将刷新缓冲区

    与文件的连接关闭后,并不会删除流,fstream流对象和它管理的缓冲区仍然存在,
    可以将流重新连接到文件。

    5.一个简单的读写文件示例

    #include<iostream>
    #include<fstream>
    #include<string>
    using namespace std;
    const string filename="test.txt";
    int main()
    {
    ofstream fout(filename.c_str());
    if(!fout.is_open())
    {
    cerr<<"无法打开文件 "<<filename<<endl;
    exit(0);
    }
    cout<<"输入密码:";
    float secret;
    cin>>secret;
    fout<<secret<<endl;
    fout.close();
    
    ifstream fin(filename.c_str());
    if(!fin.is_open())
    {
    cerr<<"无法打开文件 "<<filename<<endl;
    exit(0);
    }
    cout<<"输入的密码为:
    ";
    char ch;
    while(fin.get(ch))
    cout<<ch;
    fin.close();
    return 0;
    }

    程序中is_open()函数,是用来检查文件是否被打开
    流对象的状态包括:
    一切顺利,已达到文件尾,I/O操作失败等。如果一切顺利,流状态设置为0,否则设置为1。

    6.打开多个文件
    1)需要同时打开多个文件,则需要为每个文件创建一个流。
    2)需要依次打开一组文件,可以只打开一个流,将它依次关联到各个文件。

    如下例所示:

    ifstream fin;
    fin.open("test.txt");
    fin.close();
    fin.clear();
    fin.open("test2.txt");
    fin.close();

    7.文件模式

    常量 含义
    ios_base::in 打开文件,以便读取
    ios_base::out 打开文件,以便写入
    ios_base::ate 打开文件,并移到文件尾,和ios_base::app的区别是,后者只能在文件尾写入,前者只是将写入指针初始化在文件尾
    ios_base::app 追加到文件尾
    ios_base::trunc 如果文件存在,则清空文件内容
    ios_base::binary 二进制文件

    对于ifstream open(),默认的模式为ios_base::in
    对于ofstream open(),默认的模式为ios_base::out|ios_base::trunc,打开并清空文件

    8.二进制模式 ios_base::binary 

    文件的存储类型有两种,文本格式或二进制格式
    文本格式便于读取,而二进制格式更加精确,占用空间小,读取速度快。
    写操作:

    fout.write((char*)&T,sizeof T);

    读操作:

    fin.read((char*)&T,sizeof T);

    注意需要将类型实例地址,强制转换为char*类型。

    9.随机存取

    随机存取是指,读写指针直接移动到文件的任何位置。

    跳转函数:

    istream & seekg(streamoff,ios_base::seekdir);//相对地址
    istream & seekg(streampos);//绝对地址

    第一个方法的意思是,离seekdir参数指定文件位置,距离streamoff的位置。
    其中,streamoff单位的是字节,seekdir表示文件的三个位置(顶端ios_base::beg,底端ios_base::end,当前位置ios_base::cur)

    第二个方法的意思是,离文件开头streampos的位置
    streampos表示文件中的绝对位置,单位是字节

    seekg()
    移到文件开头

    tellg()
    返回读写指针当前的位置

    下面,我们用二进制文件模式,写一个简单的随机存取示例:

    #include<iostream>
    #include<fstream>
    #include<iomanip>
    const int LIM=20;
    struct planet
    {
        char name[LIM];
        double population;
        double g;
    };
    const char *file = "planets.dat";
    inline void eatline(){while(std::cin.get()!='
    ') continue;}
    int main()
    {
        using namespace std;
        planet pl;
        cout<<fixed;
    
        fstream finout;
        finout.open(file,ios_base::in|ios_base::out|ios_base::binary);
        int ct = 0;
        if(finout.is_open())
        {
            finout.seekg(0);
            cout<<"contents of file "<<file<<endl;
            while(finout.read((char *)&pl,sizeof pl))
            {
                cout<<ct++<<":"<<setw(20)<<pl.name<<":"
                    <<setprecision(0)<<setw(12)<<pl.population
                    <<setprecision(2)<<setw(6)<<pl.g<<endl;
            }
            if(finout.eof())
                finout.clear();
            else{
                cerr<<"无法打开文件 "<<file<<endl;
                exit(0);
            }
        }
        else{
            cerr<<"无法打开文件 "<<file<<endl;
            exit(0);
        }
        cout<<"enter record number to change:";
        long rec;
        cin>>rec;
        eatline();
        if(rec<0||rec>=ct)
        {
            cerr<<"无效 index number"<<endl;
            exit(0);
        }
        streampos place = rec*sizeof pl;
        finout.seekg(place);
        if(finout.fail())
        {
            cerr<<"无法找到 index number"<<endl;
            exit(0);
        }
        finout.read((char *)&pl,sizeof pl);
        cout<<"找到的 index number"<<endl;
        cout<<rec<<":"<<setw(20)<<pl.name<<":"
                    <<setprecision(0)<<setw(12)<<pl.population
                    <<setprecision(2)<<setw(6)<<pl.g<<endl;
        if(finout.eof())
            finout.clear();
        cout<<"输入name:";
        cin.get(pl.name,LIM);
        eatline();
        cout<<"population:";
        cin>>pl.population;
        cout<<"g:";
        cin>>pl.g;
        finout.seekp(place);
        finout.write((char*)&pl,sizeof pl)<<flush;
        if(finout.fail())
        {
            cerr<<"写失败 index number"<<endl;
            exit(0);
        }
    
        ct = 0;
        finout.seekg(0);
        cout<<"contents of file "<<file<<endl;
        while(finout.read((char *)&pl,sizeof pl))
        {
            cout<<ct++<<":"<<setw(20)<<pl.name<<":"
                <<setprecision(0)<<setw(12)<<pl.population
                <<setprecision(2)<<setw(6)<<pl.g<<endl;
        }
        finout.close();
        cout<<"Done.
    ";
        return 0;
    }

    程序中,我们使用了一个特别的流管理对象fstream,
    fstream继承子iostream,而iostream继承自istream和ostream
    因此fstream继承了两个缓冲区,一个用于输入,一个用于输出
    并能同步化两个缓冲区的处理。即输入指针和输出指针的位置始终相同。
    这样用一个流管理对象,就可以同时进行读和写。

    参考资料:《C++ Primer.Plus》 pp.768-788

  • 相关阅读:
    [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树
    [BZOJ3230] 相似字串 后缀数组+RMQ
    [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树
    [BZOJ4044]Virus synthesis 回文自动机的DP
    [BZOJ2055]80人环游世界 有上下界最小费用最大流
    [BZOJ2502]清理雪道 有上下界网络流(最小流)
    [BZOJ2095][Poi2010]Bridges 最大流(混合图欧拉回路)
    [BZOJ2288&BZOJ1150]一类堆+链表+贪心问题
    [BZOJ4820]硬币游戏 KMP+高斯消元
    [BZOJ1559]密码 AC自动机+状压
  • 原文地址:https://www.cnblogs.com/shijingjing07/p/5580409.html
Copyright © 2020-2023  润新知