美文网首页
C语言(五-文件)

C语言(五-文件)

作者: 强某某 | 来源:发表于2020-06-24 13:20 被阅读0次

    标准IO库函数对磁盘文件得读取特点

    1.jpg

    文件缓冲区是库函数申请得一段内存,由库函数对其进行操作,程序员没必要知道存放在哪里

    缓冲区分类

    1. 行缓冲

    标准io库函数,往标准输出(屏幕)输出东西得时候是行缓冲,所谓行缓冲就是缓冲区碰到换行符得时候才刷新缓冲区;默认行缓冲得大小为1024字节,如果满了即使不换行也会输出

    1. 全缓冲

    标准io库函数,往普通文件读写数据得,是全缓冲,碰到换行符也不刷新缓冲区,即缓冲区满了,才刷新缓冲区

    刷新缓冲区得情况

    • 缓冲区满了,刷新缓冲区
    • 人为刷新缓冲区fflush(文件指针)
    • 程序正常结束 会刷新缓冲区
    1. 无缓冲

    在读写文件得时候通过系统调用io(read write),对文件进行读写数据,这个时候是无缓冲得,即写数据会立马进入文件,读数据会立马进入内存

    写文件流程

    应用程序空间->内核空间->驱动程序->硬盘上

    应用程序和内核程序运行在不同得空间里,目的是为了保护内核

    设置缓冲区目的

    通过缓冲可以减少进出内核得次数,以提高效率

    磁盘文件得分类

    一个文件通常是磁盘上一段名命得存储区,计算机得存储在物理上是二进制得,所以物理上所有磁盘文件本质上都是一样的:以字节为单位进行顺序存储,从用户或者操作系统使用得角度(逻辑上)把文件分为:

    • 文本文件:基于字符编码得文件
    • 二进制文件:基于值编码得文件

    文本文件

    基于字符编码,常见编码有ASCII,UNICODE等,一般可以使用文本编辑器直接打开

    例如:数字5678得以ASCII存储形式为:

    ASCII码:00110101 00110110 00110111 00111000

    还有歌词文件(lrc):文本文件

    二进制文件

    基于值编码,自己根据具体应用,指定某个值得意思,把内存中得数据按其在内存中得存储形式原样输出到磁盘上,一般需要自己判断或使用特定软件分析数据格式

    例如:数5678得存储形式为:

    二进制码:00010110 00101110

    音频文件(mp3):二进制文件
    图片文件(bmp)文件,一个像素点由两个字节来描述*****######&&&&&
    * 代表红色得值
    # 代表绿色得值
    & 代表蓝色得值
    二进制文件以位来表示一个意思
    

    对比

    译码:
    文本文件编码基于字符定长,译码容易;
    二进制文件编码是变长得,译码难一些(不同得二进制文件格式,有不同得译码方式)
    
    空间利用率:
    二进制文件用一个比特来代表一个意思(位操作);
    而文本文件任何一个意思至少是一个字符
    
    可读性:
    文本文件用通用得记事本工具就几乎可以浏览所有文本文件
    二进制文件需要一个具体得文件解码器,比如BMP文件,必须用读图软件
    

    文件指针

    文件指针在程序中用来标识一个文件得,在打开文件得时候得到文件指针,文件指针就用来代表咱们打开得文件。

    咱们对文件进行读写关闭等操作的时候,对文件指针进行操作即可,即咱们将文件指针,传给读写关闭等函数。

    定义文件指针得一般形式:
    FILE * 指针变量标识符;
    FILE 为大写,需要包含<stdio.h>
    FILE是系统使用typedef定义出来得有关文件信息得一种`结构体类型`,结构体中有文件名、文件状态和文件当前位置等信息
    
    FILE在stdio.h文件中得文件类型声明:
    typedef struct{
        short level;//缓冲区满或空得程度
        unsigned flags;//文件状态标志
        char fd;//文件描述符
        unsigned charhold;//如无缓冲区不读取字符
        short bsize;//缓冲区大小
        unsigned char *buffer;//数据缓冲区得位置
        unsigned ar *curp;//指针,当前得指向
        unsigned istemp;//临时文件,指示器
        shorttoken;//用于有效性检查
    }FILE;
    
    在缓冲文件系统中每个被使用得文件都要在内存中开辟一块FILE
    类型得区域,存放与操作文件相关得信息
    

    对文件操作得步骤:

    1. 对文件进行读写等操作之前要打开文件得到文件指针
    2. 可以通过文件指针对文件进行读写等操作
    3. 读写等操作完毕之后,要关闭文件,关闭文件之后,就不能再通过此文件指针操作文件了

    c语言中有三个特殊得文件指针无需定义,再程序中可以直接使用

    1. stdin:标准输入 默认为当前终端(键盘)

    使用scanf、getchar函数默认从此终端获取数据

    1. stdout:标准输出 默认为当前终端(屏幕)

    printf、puts函数默认输出信息到此终端

    1. stderr:标准错误输出设备文件 默认为当前终端(屏幕)

    程序出错使用:perror函数是信息打印再此终端

    打开文件

    FILE *fopen(const char *path,const char *mode);

    函数说明:fopen函数的功能是打开一个已经存在的文件,并返回这个文件的文件指针(文件的标志),或者创建一个文件,并打开此文件,然后返回文件的标示

    参数1:打开的文件得路径
    1. 绝对路径
    2. 相对路径
    
    参数2:文件打开的方式,(只读、只写、读写等等)
    r w a +
    
    注意:反是加b的都是操作二进制文件,但是一般都是文本文件读写,所以不常用
    
    返回值:
    成功,打开的文件对应的文件指针
    失败:返回NULL
    
    模式 功能
    r或rb 以只读方式打开一个文本文件(不创建文件)
    w或wb 以写方式打开文件(如果文件存在则使文件长度截断为0字节-清空,如果文件不存在-创建一个文件)
    a或ab 以添加方式打开文件,即在末尾添加内容,当文件不存在时,创建文件用于写
    r+或rb+ 以可读、可写的方式打开文件(不创建新文件)
    w+或wb+ 以可读、可写的方式打开文件(如果文件存在则使文件长度为0-清空,存在则创建一个文件)
    a+或ab+ 以添加方式打开文件,打开文件并在末尾更改文件(如果文件不存在则创建文件)

    关闭文件

    函数的定义:
    int fclose(FILE *fp);
    关闭fp所代表的文件
    注意:一个文件只能关闭一次,不能多次关闭。
    关闭文件之后就不能再文件指针对文件进行读写等操作了
    
    返回值:
    成功返回0
    失败返回非0
    
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
        FILE *fp;
        fp=fopen("C:/User/fil.txt","r");
        if(fp==NULL){
            //直接错误退出
           return -1;
        }
        fclose(fp);
        return 0;
    }
    

    读写一个字符

    函数定义:int fgetc(FILE *stream)
    fgetc从stream所标志的文件中读取一个字符,将字节返回
    
    返回值:
    以t的方式:读到文件结尾返回EOF
    以b的方式:督=读到文件结尾,使用feof判断结尾
    
    函数的定义:int fputc(int c,FILE *stream)
    fputc将c的值写道stream所代表的文件中
    
    返回值:
    如果输出成功,则返回输出的字节值
    如果输出失败,则返回一个EOF
    
    EOF是再stdio.h文件中定义的符号常量,值为-1
    
    注意: 打开文件的时候,默认读写文件的位置在文件的开始,
    如果以a的方式打开读写位置再文件的末尾;向文件在读取字节或者写入字节的时候,读写
    位置会往末尾方向偏移,读写多少个字节,读写位置就往文件的末尾方向偏移多少个字节
    
    读文件判断是否结束:==EOF则结束
    

    读写一个字符串

    函数定义:
    char *fgets(char *s,int siez,FILE *stream);
    函数说明:
    从stream所指得文件中读取字符,在读取得时候碰到换行符或者是
    碰到文件得末尾停止读取,或者是读取到size-1个字节停止读取,
    在读取得内容后面会加一个\0,作为字符串得结尾
    
    返回值:
    成功返回目的数组得首地址,即S
    失败返回NULL
    
    
    函数定义:
    int fputs(consy char *s,FILE *stream);
    
    函数说明:
    将s指向得字符串,写到stream所代表得文件中
    返回值:
    成功返回写入得字节数
    失败返回-1
    
    int main(int argc, char *argv[])
    {
        FILE *fp;
        fp=fopen("C:/User/fil.txt","r");
        if(fp==NULL){
            //直接错误退出
           return -1;
        }
        //读文件
        char buf[32]="";
        //fgets每次读取时最多读取文件一行内容,遇到换行符立刻返回
        //如果想要读取的字节数小于一行内容,则只会读取第二个参数-1个字节,最后补\0
        fgets(buf,8,fp);
        printf("buf=%s\n",buf);
        //写文件
        fputs("66666666\n",fp);
        fputs("nihao",fp);
        fclose(fp);
        return 0;
    }
    

    读文件

    函数的定义:
    size_t_fread(void *ptr,size_t_size,size_t_nmemb,FILE *stream);
    函数说明:
    fread函数从stream所标识的文件中读取数据,一块是size字节,
    龚nmemb块,存放到ptr指向的内存里
    
    返回值:
    实际读到的块数
    
    例子:
    int num;
    num=fread(str,100,3,fp);
    从fp所代表的文件中读取内容存放到str指向的内存中,读取的字节数为,每块100字节,3块。
    返回值num,如果读到300个字节返回值Num为3,如果大于等于200小
    于300返回2,大于等于100小于200返回1,不到100字节返回0
    
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
        FILE *fp;
        fp=fopen("C:/User/fil.txt","r");
        if(fp==NULL){
            //直接错误退出
           return -1;
        }
        //读文件
        int num;
        char buf[128]="";
        num=fread(buf,5,4,fp);
        printf("buf=%s\n",buf);
        printf("num=%d\n",num);
        return 0;
    }
    

    写文件

    函数的定义:
    size_t_fwrite(void *ptr,size_t_size,size_t_nmemb,FILE *stream);
    
    函数的说明:
    fwrite函数将ptr指向的内存里的数据,向stream所标志的文件中写入数据,一块是size字节,共nmemb块。
    
    返回值:实际写入的块数
    
    #include <stdio.h>
    
    typedef struct{
        int a;
        int b;
        char c;
    }MSG;
    
    int main(int argc, char *argv[])
    {
        FILE *fp;
        fp=fopen("C:/User/fil.txt","r");
        if(fp==NULL){
            //直接错误退出
           return -1;
        }
        //写文件:使用fwirte向文件写入一个结构体,因为fwrite的第一个参数是void类型的指针,
        //所以不光可以写文件,还可以写结构体等类型,只要符合即可
        MSG msg[4]={
          1,2,'a',3,4,'b',5,6,'c',7,8,'d'
        };
        fwrite(msg,sizeof(msg),4,fp);
        //注意:读写代码都写在这里的话,则读写共用同一个偏移量
        //如果写文件结束起始偏移量在最后这时候想读文件需要重置偏移量
    
        //将文件的偏移量设置为文件的起始位置
        rewind(fp);
    
    
        MSG rcv[4];
        fread(rcv,sizeof(MSG),4,fp);
        int i;
        for(i =0;i<4;i++){
            printf("%d -%d -%d\n",rcv[i].a,rcv[i].b,rcv[i].c);
    
        }
        return 0;
    }
    

    格式化读写文件

    函数调用:
    fprintf(文件指针,格式字符串,输出表列);
    fscanf(文件指针,格式字符串,输出表列);
    
    函数功能:从磁盘文件中读入或输出字符
    
    fprintf和printf函数类似:
    printf是将数据输出到屏幕上(标准输出)
    fprintf函数是将数据输出到文件指针所指定的文件中
    
    fscanf和scanf函数类似:
    scanf是从键盘(标准输入)获取输入
    fscanf是从文件指针所标示的文件中获取输入
    
    
    char ch1='a';
    int num1=50;
    fprintf(fp,"%c %d\n",ch1,num1);
    rewind(fp);
    fscanf(fp,"%c %d\n",&ch1,&num1);
    

    随机读写

    上面的所有读写都是顺序读写,从头开始;但是实际经常需要读取某一部分内容,为了解决这个问题,可以移动文件内部的位置指针到需要读写的位子,再进行读写,这种被称为随机读写。实现随机读写的关键是要按要求移动位置指针,这被称为文件的定位

    完成文件定位的函数:
    rewind、fseek函数
    
    1. rewind复位读写位置
    rewind函数
        void rewind(文件指针);
    把文件内部的位置指针移动到文件首部
    
    2. ftell测文件读写位置距文件开始有多少个字节
    long ftell(文件指针);
    取地文件流目前的读写位置
    
    返回值:返回当前读写位置(距离文件起始的字节数),出错时返回-1
    
    3. int fseek(FILE * stream,long offset,int whence);
    //int fseek(文件类型指针,位移量,起始点);
    
    函数功能:
    移动文件流的读写位置
    
    参数:
    whence起始位置
        文件开头 SEEK_SET 0
        文件当前位置  SEEK_CUR 1
        文件末尾   SEEK_END  2
        
    位移量:以起始点为基点,向前、后移动的字节数,正数往文件末尾方向移动,负数反之
    
    fseek(fp,50,SEEK_SET);
    

    相关文章

      网友评论

          本文标题:C语言(五-文件)

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