美文网首页
文件操作

文件操作

作者: 薛落花随泪绽放 | 来源:发表于2022-10-03 23:17 被阅读0次

文件基本概念和文件流类

文件的概念

在计算机中,通常将一些内容相关的信息组织起来保存在一起并用一个名字标识,这就是文件。

C++根据文件数据的编码方式不同分为文本文件和二进制文件。

C++文件流类

流是一个逻辑概念,是对所有外部设备的逻辑抽象。

C++标准库中有3个流类可以用于文件操作。

  • ifstream:用于从文件中读取数据
  • ofstream:用于向文件中写入数据
  • fstream:既可用于从文件中读取数据,又可用于向文件中写入数据。

打开和关闭文件

打开文件

在对文件进行读写操作之前,先要打开文件,打开文件有两个目的

  • 建立关联;
  • 指明文件的使用方式和文件格式。

打开文件的方式有两种

  1. 先建立流对象,然后调用open()函数连接外部文件
流类名 对象名;
对象名.open(文件名,模式);
  1. 调用流类带参数的构造函数,在建立流对象的同时连接外部文件。
流类名 对象名(文件名,模式);

表8-1 文件打开模式标记

模式标记 适用对象 作用
ios::in ifstream/fstream 以读方式打开文件。如果文件不存在,则打开出错
ios::out ofstream/fstream 以写方式打开文件。如果文件不存在,则新建该文件;如果文件已经存在,则打开时清除原来的内容
ios::app ofstream 以追加方式打开文件,用于在文件尾部添加数据。如果文件不存在,则新建该文件
ios::ate ofstream 打开一个已有的文件,并将文件读指针指向文件末尾。如果文件不存在,则打开出错。
ios::trunc ofstream 删除文件现有内容。单独使用时与ios::out相同
ios::binary ifstream/ofstream/fstream 以二进制方式打开文件。若不指定此模式,则以默认的文本模式打开文件
ios::in | ios::out fstream/ofstream 打开已存在的文件,即可读取其内容,也可向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。
ios::in |ios::out|ios::trunc fstream 打开文件,即可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容,如果不存在,则新建。

例如,要从data.txt中读取数据

ifstream inFIle;
inFile.open("data.txt",ios::in);
或
ifstream inFIle("data.txt",ios::in);

关闭文件

使用fstream中的成员函数close()关闭文件。
程序8-1 建立流对象,然后调用open()函数连接外部文件

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    ifstream inFile;
    inFile.open("d:\\tmp\\test.txt",ios::in);
    if(inFile)
    {
        cout<<"成功打开文件:d:\\tmp\\test.txt\n";
        inFile.close();
    }
    else
        cout<<"打开文件失败:d:\\tmp\\test.txt\n";
    ofstream outFile;
    outFile.open("test1.txt",ios::out);
    if(!outFile)
        cout<<"error1"<<endl;
    else
    {
        cout<<"成功打开文件:test1.txt\n";
        outFile.close();
    }
    outFile.open("tmp\\test2.txt",ios::out|ios::in);
    if(outFile)
    {
        cout<<"成功打开文件:tmp\\test2.txt\n";
        outFile.close();
    }
    else
        cout<<"error2"<<endl;
    fstream ioFile;
    ioFile.open("..\\test3.txt",ios::out|ios::in|ios::trunc);
    if(!ioFile)
        cout<<"error3"<<endl;
    else
    {
        cout<<"成功打开文件: ..\\test3.txt\n"<<endl;
        ioFile.close();
    }
    return 0;
}

程序8-2 调用流类带参数的构造函数打开文件

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    ifstream inFile("d:\\tmp\\test.txt",ios::in);
    if(inFile)
    {
        cout<<"成功打开文件:d:\\tmp\\test.txt\n";
        inFile.close();
    }
    else
        cout<<"打开文件失败: d:\\tmp\\test.txt\n";
    ofstream outFile("test1.txt",ios::out);
    if(!outFile)
    {
        cout<<"error1"<<endl;
    }
    else
    {
        cout<<"成功打开文件: test1.txt\n";
        outFile.close();
    }
    fstream outFile2("tmp\\test2.txt",ios::out|ios::in);
    if(outFile)
    {
        cout<<"成功打开文件: tmp\\test2.txt\n";
        outFile.close();
    }
    else
        cout<<"error2"<<endl;
    return 0;
}

文件读写操作

读写文本文件

C++将文件看成顺序排列的无结构的字节流。

程序8-3 对文本文件score.txt进行输入/输出

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    char id[11],name[21];
    int score;
    ofstream outFile;
    outFile.open("score.txt",ios::out);
    if(!outFile)
    {
        cout<<"创建文件失败"<<endl;
        return 0;
    }
    cout<<"请输入:学号       姓名  成绩(以Ctrl+Z结束输入)\n";
    while(cin>>id>>name>>score)
        outFile<<id<<" "<<name<<" "<<score<<endl;
        outFile.close();
        return 0;
}

输入如下:


image.png

内容如下


image.png

程序8-4 读入学生成绩文件score.txt并显示内容

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main()
{
    char id[11],name[21];
    int score;
    ifstream inFile;
    inFile.open("score.txt",ios::in);
    if(!inFile)
    {
        cout<<"打开文件失败"<<endl;
        return 0; 
    }
    cout<<"学生学号\t 姓名\t\t     成绩\n";
    while(inFile>>id>>name>>score)
        cout<<left<<setw(10)<<id<<" "<<setw(20)<<name<<" "<<setw(3)<<right<<score<<endl;
    inFile.close();
    return 0;
}

学生学号         姓名                成绩
20180001        zhangsan              90
2018001002      lisi                   9
2018001003      wangwu                85
2018001004      zhangsanfeng         100
2008001005      zhouwuzhengwangyishi 100

程序8-5 读入文本文件,加上行号后显示内容

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main()
{
    char ch,filename[20];
    int count=0;
    bool newline = true;
    cout<<"请输入文件名: ";
    cin>>filename;
    ifstream inFile(filename,ios::in);
    if(!inFile)
    {
        cout<<"打开文件失败"<<endl;
        return 0;
    }
    while((ch=inFile.get())!=EOF)
    {
        if(newline)
        {
            cout<<setw(4)<<++count<<':';
            newline=false;
        }
        if(ch=='\n')
            newline=true;
        cout<<ch;
    }
    inFile.close();
    return 0;
}

请输入文件名: score.txt
   1:20180001 zhangsan 90
   2:2018001002 lisi 9
   3:2018001003 wangwu 85
   4:2018001004 zhangsanfeng 100
   5:2008001005 zhouwuzhengwangyishi 100

程序8-6 对文本文件的内容排序,将结果输出到另一个文件

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
const int MAX_NUM = 1000;
class CStudent
{
    public:
        char id[11];        //学号。为10位,以'\o'结尾
        char name[21];      //姓名。不超过20个字符
        int score;          //成绩 
}stu[MAX_NUM];      //存放文件中读入的整数

int MyCompare(const void * e1,const void * e2)
{
    return (*(CStudent *)e1).score-(*(CStudent *)e2).score; 
} 

int main()
{
    ifstream srcFile("score.txt",ios::in);
    if(!srcFile)
    {
        cout<<"opening source file error."<<endl;
        return 0;
    }
    ofstream destFile("out.txt",ios::out);
    if(!destFile)
    {
        srcFile.close();
        cout<<"opening destionation file error."<<endl;
        return 0;
    }
    int n = 0;
    cout<<"排序前:\n";
    while(srcFile>>stu[n].id>>stu[n].name>>stu[n].score)
    {
        cout<<stu[n].id<<" "<<stu[n].name<<" "<<stu[n].score<<endl;
        n++;
    }
    qsort(stu,n,sizeof(CStudent),MyCompare);
    cout<<"排序后: \n";
    for(int i=0;i<n;++i)
    {
        cout<<stu[i].id<<" "<<stu[i].name<<" "<<stu[i].score<<endl;
        destFile<<stu[i].id<<" "<<stu[i].name<<" "<<stu[i].score<<endl;
    }
    destFile.close();
    srcFile.close();
    return 0;
}

排序前:
20180001 zhangsan 90
2018001002 lisi 9
2018001003 wangwu 85
2018001004 zhangsanfeng 100
2008001005 zhouwuzhengwangyishi 100
排序后:
2018001002 lisi 9
2018001003 wangwu 85
20180001 zhangsan 90
2008001005 zhouwuzhengwangyishi 100
2018001004 zhangsanfeng 100

读写二进制文件

文本文件在存储数据时是以ASCII码形式保存数据的。二进制数据文件以基本类型数据的二进制形式存放。

C++用binary方式打开二进制文件,调用ifstream或fstream的read()成员函数从文件中读取数据,调用ofstream或fstream的write()成员函数向文件中写入数据。

  1. 用ostream::write()成员函数写文件
    ostream和fstream的write()成员函数继承自ostream类。
ostream & write(char *buffer,int nCount);

程序8-7 用二进制文件保存学生信息

#include <iostream>
#include <fstream>
using namespace std;
class CStudent
{
    public:
        char id[11];
        char name[21];
        int score;
};

int main()
{
    CStudent stu;
    ofstream outFile("students.dat",ios::out|ios::binary);
    if(!outFile)
    {
        cout<<"创建文件失败"<<endl;
        return 0;
    }
    cout<<"请输入:学号 姓名 成绩(以Ctrl+Z结束输入)\n";
    while(cin>>stu.id>>stu.name>>stu.score)
        outFile.write((char *)&stu,sizeof(stu));
    outFile.close();
    return 0;
}

程序8-8 向二进制文件中追加数据

#include <iostream>
#include <fstream>
using namespace std;
class CStudent
{
    public:
        char id[11];
        char name[21];
        int score;
};

int main()
{
    char ch;
    cout<<"确实需要向文件中追加新数据吗(Y/N)?";
    cin>>ch;
    if(ch=='Y' || ch=='y')
    {
        CStudent stu;
        ofstream outFile("students.dat",ios::app|ios::binary);
        if(!outFile)
        {
            cout<<"以追加方式打开文件失败"<<endl;
            return 0;
        }
        cout<<"请输入: 学号 姓名 成绩(以Ctrl+Z结束输入)\n";
        while(cin>>stu.id>>stu.name>>stu.score)
            outFile.write((char*)&stu,sizeof(stu));
        outFile.close();
    }
    return 0;
}
  1. 用istream::read()成员函数读文件
    继承自类istream
istream &read(char * buffer,int nCount);
  1. 用ostream::gcount()成员函数得到读取字节数
int gcount();

程序8-9 从二进制文件中读取数据

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;

class CStudent
{
    public:
        char id[11];
        char name[21];
        int score;
};

int main()
{
    CStudent stu;
    int count=0,nbyte=0;
    ifstream inFile("students.dat",ios::in|ios::binary);
    if(!inFile)
    {
        cout<<"创建文件失败"<<endl;
        return 0;
    }
    cout<<"学生学号   姓名\t\t\t成绩\n";
    while(inFile.read((char *)&stu,sizeof(stu)))
    {
        cout<<left<<setw(10)<<stu.id<<" "<<setw(20)<<stu.name<<" "<<setw(3)<<right<<stu.score<<endl;
        count++;
        nbyte += inFile.gcount();
    }
    cout<<"共有记录数: "<<count<<",字节数: "<<nbyte<<endl;
    inFile.close();
    return 0;
}

学生学号   姓名                 成绩
2019001001 zhangsan              90
2019001002 LiSi                 100
2019001003 WangWu                78
2008001005 xuexiansheng         102
2011002004 qixiansheng          100
共有记录数: 5,字节数: 180

用成员函数put()和get()读写文件

可以用类ifstream和类fstream的成员函数get()从文件中一次读取一个字节,也可以用类ofstream和类fstream的成员函数put()向文件中一次写入一个字节。

函数get()有3中主要形式

  1. int get();
  2. istream& get(char &rch);
  3. istream & get(char *pch,int nCount,char delim='\n');

函数put()语法格式

ostream &put(char ch);

程序8-10 文件复制

#include <iostream>
#include <fstream>
using namespace std;

int main(int argc,char * argv[])
{
    if(argc != 3)       //判断main的参数是否位3个 
    {
        cout<<"使用方法错误。正确的命令格式:mycopy SourceFile NewFile"<<endl;
        return 0;
    }
    ifstream inFile(argv[1],ios::binary|ios::in);
    if(!inFile)
    {
        cout<<"Source file open error."<<endl;
        return 0;
    }
    ofstream outFile(argv[2],ios::binary|ios::out);
    if(!outFile)
    {
        cout<<"New file open error."<<endl;
        inFile.close();
        return 0;
    }
    
    char c;
    while(inFile.get(c))
        outFile.put(c);
    outFile.close();
    inFile.close();
    return 0;
}

随机访问文件

如果一个文件只能进行顺序存取操作,称为顺序文件。典型的是键盘、显示器和保存在磁带上的文件。

如果一个文件可以在文件的任意位置进行存取操作,称为随机文件。磁盘文件就是随机文件。

在访问文件的过程中,若严格按照数据保存的次序从头到尾访问文件,则称为顺序访问。

若不必按照数据的存储次序访问文件,而是要根据需要在文件的不同位置进行访问,则称为随机访问。

在C++中,每个流都有一个”流指针“,由系统控制,会随着对流的各种操作在字节流中移动。

在类istream、类ifstream和类fstream中有成员函数seekg(),可以设置文件读指针的位置;

在类ostream、类ofstream和类fstream中有成员函数seekp(),可以设置文件的写指针位置。

类istream中与位置指针相关的函数

  1. 移动读指针函数
    istream & seekg(long pos);将读指针设置为pos。
    istream & seekg(long offset,ios::seek_dir dir); 将读指针按照seek_dir的指示移动offset个字节。

  2. 返回读指针当前位置值的函数
    long tellg(); 返回值为流中读指针的当前位置。

类ostream中与位置指针相关的函数

  1. 移动写指针函数
    ostream & seekp(long pos);
    ostream & seekp(long offset,ios::seek_dir dir);

  2. 返回写指针当前位置的函数
    long tellp();

程序8-11 修改程序8-7,

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
class CStudent
{
    public:
        char id[11];
        char name[21];
        int score;
};

int main()
{
    CStudent stu;
    int count = 0,nbyte=0;
    ifstream inFile("students.dat",ios::in|ios::binary);
    if(!inFile)
    {
        cout<<"创建文件失败"<<endl;
        return 0;
    }
    else
    {
        cout<<"打开文件时位置指针: "<<inFile.tellg()<<endl;
        cout<<"     每个记录大小: "<<sizeof(CStudent)<<endl;
    }
    cout<<"学生学号   姓名\t\t\t成绩\t流指针";
    while(inFile.read((char *)&stu,sizeof(CStudent)))
    {
        cout<<left<<setw(10)<<stu.id<<" "<<setw(20)<<stu.name<<" "<<setw(3)<<right<<stu.score<<"\t"<<inFile.tellg()<<endl;
        count++;
        nbyte += inFile.gcount();
    }
    cout<<"读取文件结束时位置指针: "<<inFile.tellg()<<endl;
    cout<<"共有记录数: "<<count<<",字节数: "<<nbyte<<endl;
    inFile.clear();
    inFile.seekg(0);
    cout<<"位置指针: "<<inFile.tellg()<<endl;
    inFile.read((char *)&stu,sizeof(stu));
    cout<<left<<setw(10)<<stu.id<<" "<<setw(20)<<stu.name<<" "<<setw(3)<<right<<stu.score<<endl;
    inFile.seekg(0,ios::end);
    cout<<"位置指针: "<<inFile.tellg()<<endl;
    inFile.close();
    return 0;
}

打开文件时位置指针: 0
                每个记录大小: 36
学生学号   姓名                 成绩    流指针2019001001 zhangsan              90       36
2019001002 LiSi                 100     72
2019001003 WangWu                78     108
2008001005 xuexiansheng         102     144
2011002004 qixiansheng          100     180
读取文件结束时位置指针: -1
共有记录数: 5,字节数: 180
位置指针: 0
2019001001 zhangsan              90
位置指针: 180

程序8-12 读取文件,查找最高分和最低分的学生,并显示信息。

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
class CStudent
{
    public:
        char id[11];
        char name[21];
        int score;
};

int main()
{
    CStudent stu;
    int count=0,maxScore,minScore,maxNo,minNo;
    maxScore = INT_MIN;
    minScore = INT_MAX;
    maxNo = minNo = 0;
    ifstream inFile("students.dat",ios::in|ios::binary);
    if(!inFile)
    {
        cout<<"创建文件失败"<<endl;
        return 0;
    }
    while(inFile.read((char *)&stu,sizeof(CStudent)))
    {
        if(stu.score > maxScore)
        {
            maxScore = stu.score;
            maxNo = count;
        }
        else if(stu.score < minScore)
        {
            minScore = stu.score;
            minNo = count;
        }
        count++;
    }
    inFile.clear();
    inFile.seekg(sizeof(CStudent)*maxNo,ios::beg);
    inFile.read((char *)&stu,sizeof(CStudent));
    cout<<"最高分记录: "<<maxNo<<":"<<stu.id<<","<<stu.name<<","<<stu.score<<endl;
    inFile.seekg(sizeof(CStudent)*minNo,ios::beg);
    inFile.read((char *)&stu,sizeof(CStudent));
    cout<<"最低分记录: "<<minNo<<":"<<stu.id<<","<<stu.name<<","<<stu.score<<endl;
    inFile.close();
    return 0;
}

最高分记录: 3:2008001005,xuexiansheng,102
最低分记录: 2:2019001003,WangWu,78

相关文章

  • 文件操作

    文件操作 目标 文件操作的作用 文件的基本操作打开读写关闭 文件备份 文件和文件夹的操作 一. 文件操作的作用 思...

  • 文件和目录处理相关

    文件和目录处理相关 题: 考点:文件操作/写入操作; 延伸:目录操作函数,其他文件操作; 文件读写操作 文件系统函...

  • 09-文件操作

    一、文件操作流程 a.普通文件操作流程: 打开文件 操作文件 关闭文件 b. json文件操作流程: open(文...

  • VBS文件操作

    VBS文件操作'操作文本文件,操作fso对象(文件对象操作) --------------------------...

  • 文件操作

    文件操作:打开文件、读写文件、操作文件内容 写入文件操作:(把大象装入冰箱)1.打开文件 ...

  • 类的补充

    一.复习 1.文件操作a.操作流程:打开文件(open),操作文件,关闭文件with open() as 文件变量...

  • 文件

    目标 文件操作的作用 文件的基本操作打开读写关闭 文件备份 文件和文件夹的操作 一. 文件操作的作用 思考:什么是...

  • 16总 正则表达式

    复习: 1.文件操作a.操作流程: 打开文件(open) --- 操作文件 --- 关闭文件(close)with...

  • 2018-09-10

    01-recode 1.文件操作a.操作流程:打开文件---》操作文件----》关闭文件with open() ...

  • 2018-09-10 day16总结

    1.文件操作 a.操作流程:打开文件(open)-操作文件-关闭文件(close)with open() as 文...

网友评论

      本文标题:文件操作

      本文链接:https://www.haomeiwen.com/subject/nxfeartx.html