12.文件

知识点一:文件的存取过程

缓冲区的目的:提高存储效率磁盘使用寿命

文件的存取过程

知识点二:磁盘文件分类

物理上所有的磁盘文件都是二进制存储,以字节为单位顺序存储

逻辑上的文件分类:

     文本文件:基于字符编码的文件,如ASCII、UNICODE等,可以文件编辑器直接打开

     二进制文件:基于值编码的文件,数据在内存原样输出到磁盘,需要自己判断或使用特定软件分析数据格式

总结:

    (1)译码:文件文件编码基于字符定长,译码容易些。二进制文件编码变长,译码难一些(不同二进制文件格式,有不同的译码方式)

    (2)空间利用率:二进制文件用一个比特来代表一个意思(位操作)。文本文件任何一个符号需要一个字节

    (3)可读性:文本文件用通用记事本根据几乎可以浏览所有文本文件。二进制文件需要一个具体的文件解码器

知识点三:文件指针

文件指针1
typedef struct
{
	short level;			//缓冲区“满”或“空”的程度
	unsigned flags;			//文件状态标志
	char fd;			//文件描述符
	unsigned char hold;		//如无缓冲区不读取字符
	short bsize;			//缓冲区大小
	unsigned char *buffer;	//数据缓冲区的位置
	unsigned char *curp;	//指针,当前的指向
	unsigned istemp;		//临时文件,指示器
	short token;			//用于有效性检查
}FILE;

注意:不要关心FILE的细节只需要会用FILE定义指针变量就行:FILE *fp=NULL;

C语言有三个特殊的文件指针无需定义,打开直接使用:

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

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

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

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

(3)stderr:标准出错 默认当前终端(屏幕)

    当我们程序出错或使用:perror函数时信息打印在此终端

知识点四:打开一个文件

形式:
	file* fp = null;	//定义一个FILE类型的指针接收返回值
	fp = fopen(文件名,文件使用方式);
参数:
	文件名:要打开的文件名字,可以包含路径信息
	文件使用方式:“读”、“写”、“文本”或“二进制”等
返回值:成功返回相应指针,失败返回NULL

知识点五:文件使用方式

1、r:以只读方式打开文件

    文件不存在:返回NULL

    文件存在:返回文件指针,进行后续读操作

2、w:以只写方式打开文件

    文件不存在:以指定文件名创建此文件

    文件存在:清空文件内容,进行写操作

    若文件打不开(如文件只读),返回NULL

3、a:以追加的方式打开文件(往文件的末尾写入数据)

    文件不存在:以指定文件名创建此文件(同w)

    文件存在,从文件的结尾处进行写操作

4、+:以可读可写的方式打开

5、b:以二进制的方式打开文件

6、t:以文本的方式打开文件(省略)

知识点六:打开方式的组合形式

模式功能
r或rb以只读方式打开一个文本文件(不创建文件)
w或wb以写方式打开文件(使文件长度截断为0字节,创建一个文件)
a或ab以添加方式打开文件,即在末尾添加内容,当文件不存在时,创建文件用于写
r+或rb+以可读、可写的方式打开文件(不创建新文件)
w+或wb+以可读、可写的方式打开文件(使文件长度为0字节,创建一个文件)
a+或ab+以添加方式打开文件,打开文件并在未尾更改文件(如果文件不存在,则创建文件)

知识点七:关闭文件

形式:fclose(文件指针);	//文件指针:指向要关闭的文件
返回值:
    关闭文件成功,返回值为0
    关闭文件失败,返回值非零 

知识点八:文件的读写

1、字节读操作

ch = fgetc(fp);		//读一个字节
说明:从指定文件读一个字节赋给ch(以“读”或“读写”方式打开)
文件文件:读到结尾返回EOF
二进制文件:读到文件结尾,使用feof判断结尾

事先本地创建a.text

void test01()
{
    char buf[127]="";
    int i = 0;
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen("a.txt", "r") ;
    if(fp == NULL)
    {
        perror("fopen") ;
        return ;
    }
    //2、对文件的操作
    while(1)
    {
        //fgetc调用一次  读取到一个字节 
        buf[i] = fgetc(fp);
        if(buf[i] == EOF)//EOF表已经对到文件末尾
        {
            break ;
        }
        i++;
    }
    printf("buf = %s\n",buf);
    //3、 关闭文件
    fclose(fp);
}

2、字节写操作

形式:fputc(ch,fp);		//写一个字符
说明:把一个ch变量中的值(1个字节)写到指定文件
	如果输出成功,则返回输出的字节
	如果输出失败,则返回一个EOF
注意:EOF是在stdio.h文件中定义的符号常量,值为-1
void test01()
{
    char buf[127] = "";
    int i = 0;
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen("a.txt", "w") ;
    if(fp == NULL)
    {
        perror("fopen") ;
        return ;
    }
    //2、使用fputc进行文件的数据写入
    printf("请输入要写入文件的字符串:") ;
    fgets(buf,sizeof(buf),stdin) ;//会获取换行符
    buf[strlen(buf) - 1] = 0;//去掉键盘输入的换行符
    //将字符串buf中的元素逐个写入文件中
    while(buf[i] != '\0')
    {
        fputc(buf[i],fp);
        i++;
    }
    //3、 关闭文件
    fclose(fp);
}

3、字符串写操作

fputs("china",fp);		//写一个字符串
说明:
    向指定的文件写一个字符串
	第一个参数可以是字符串常量,字符串数组名或字符指针
	字符串末尾的'\0'不会写到文件中
void test01()
{
    char *buf[] = {"床前明月光\n","疑是地上霜\n"};
    int n = sizeof(buf)/sizeof(buf[0]);
    int i = 0;
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen("a.txt", "w");
    if(fp == NULL)
    {
        perror("fopen");
        return ;
    }
    for(i = 0;i<n;i++)
    {
		fputs(buf[i],fp);
    } 
    //3、 关闭文件
    fclose(fp);
}

4、字符串读操作

获取文件一行的数据

形式:fgets(str,n,fp);		//读取一个字符串
说明:从fp指向的文件读入n-1个字符,在读入n-1个字符之前遇到换行符或EOF,读入提前结束,并读取换行符,在最后加一个'\0',str为存放数据的首地址
返回值:
	成功:返回读到字符串的首元素地址
	失败:返回NULL
void test01()
{
    char buf[128] = "";
    char *path = "a.txt";
    //int i = 0;
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"r");        //fp = fopen("a.txt","r");
    //fp = fopen("path","r");    //err打开一个文件名叫"path"而不是path指向的文件名"c. txt"
    if(fp == NULL)
    {
        perror("fopen");
        return ;
    }
     while(1)
     {
         char *ret = NULL;         
         //从文件中读取一行数据 
         ret = fgets(buf,sizeof(buf),fp);
         if(ret == NULL)
         break;
         printf("%s\n",buf);
     }    
    //3、 关闭文件
    fclose(fp);
}

5、块读写

(1)fwrite数据块写操作

使用 fwrite 将数据块写入到文件中

形式:fwrite(buffer,size,count,fp);
参数说明:
	buffer:指向存储数据空间的首地址的指针
	size:一次写的数据块大小
	count:要写的数据块个数
	fp:指向要进行写操作的文件指针
返回值:实际写的数据块数(不是总数据大小)
typedef struct
{
    char name[16];	//姓名
    int deff;		//防御
    int atk;		//攻击
}HERO;
void test01()
{
    HERO hero[] = {{"德玛西亚",80,60},{"盲僧",90,80},{"小法", 40,85},{"小炮",50,90}};
    char *path = "a.txt";
    //int i = 0;
    int n = sizeof(hero)/sizeof(hero[0]);
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"w");
    if(fp == NULL)
    {
        perror("fopen");
        return ;
    }
    //fwrite将内存的数据原样的输出到文件中
    //写入文件的数据不便于用户查看但是不会影响程序的读
     fwrite(hero,sizeof(HERO),n,fp);    
    //3、 关闭文件
    fclose(fp);
}

(2)fread数据块读操作

使用 fread 从文件中读取数据块

形式:fread(buffer,size,count,fp);
参数说明:
	buffer:指向存储数据空间的首地址的指针
	size:一次读的数据块大小
	count:要读的数据块个数
	fp:指向要进行读操作的文件指针
返回值:实际读的数据块数(不是总数据大小)
typedef struct
{
    char name[16];	//姓名
    int deff;		//防御
    int atk;		//攻击
}HERO;
void test01()
{
    HERO hero[4]= {""};
    char *path = "a.txt";
    int i = 0;
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"r");
    if(fp == NULL)
    {
        perror("fopen");
        return ;
    }
    fread(hero,sizeof(HERO),4,fp);
    for(i=0;i<4; i++)
    {
        //printf(" 英雄姓名:《%s》,防御:%d》, 伤害:《%d》\n",hero[i].name,hero[i].deff,hero[i].atk);
        printf("英雄姓名:《%s》, 防御:《%d》,伤害:《%d》\n",(hero+i)->name,(hero+i)->deff,(hero+i)->atk);
    }    
    //3、 关闭文件
    fclose(fp);
}

6、格式化读操作

读:fprintf(文件指针,格式字符串,输出列表);
typedef struct
{
    char name[16];//姓名
    int deff;//防 御
    int atk;//攻击
}HERO;
void test01()
{
    HERO hero[]= {{"德玛西亚",80,60},{"盲僧",90,80},{"小法", 40,85},{"小炮",50,90}};
    char *path = "a.txt";
    int i = 0;
    int n = sizeof(hero)/sizeof(hero[0]);
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"w");
    if(fp == NULL)
    {
        perror("fopen");
        return ;
    }
    for(i= 0;i<n;i++)
    {
        fprintf(fp,"英雄:%s 防御:%d 攻击:%d\n",hero[i].name,hero[i].deff,hero[i].atk);
    }        
    //3、 关闭文件
    fclose(fp);
}

7、格式化写操作

写:fscanf(文件指针,格式字符串,输入列表);
typedef struct
{
    char name[16];	//姓名
    int deff;		//防御
    int atk;		//攻击
}HERO;
void test01()
{
    HERO hero[4]= {""};
    char *path = "a.txt";
    int i = 0;
    //int n = sizeof(hero)/sizeof(hero[0]);
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"r");
    if(fp == NULL)
    {
        perror("fopen");
        return ;
    }
    for(i= 0;i<4;i++)
    {
        fscanf(fp,"英雄:%s 防御:%d 攻击:%d\n", hero[i].name,&hero[i].deff,&hero[i].atk);
    }
    for(i=0; i<4; i ++)
    {
        printf("%s %d %d\n",hero[i].name,hero[i].deff,hero[i].atk);
    }
        
    //3、 关闭文件
    fclose(fp);
}

注意:

    (1)用fprintf和fscanf函数对磁盘文件读写使用方便,但在输入时要将ASCII码转换成二进制形式,在输出时将二进制形式转换成字符,花费时间较多

    (2)在内存与磁盘频繁交换数据的情况下,最好不用fprintf和fscanf函数,而用fread和fwrite函数

8、文件随机读写

void test01()
{
    char buf[128] ="";
    char *path = "a.txt";
    int i = 0;
    //int n = sizeof(hero)/sizeof(hero[0]);
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"w+");
    if(fp == NULL)
    {
        perror("fopen");
        return ;
    }
    //先往文件中写入一个字符串"hello file"
    fputs("hello file",fp);
    fclose(fp);
    
    //重新打开文件让文件的流指针 回到文件首部
    fp = fopen(path,"r");
    //在从文件找那个读取该字符串    
    fgets(buf,sizeof(buf),fp);
    printf("buf = %s\n",buf);        
    //3、关闭文件
    fclose(fp);
}

     如果在写的步骤中没有关闭后再打开文件则会读取到右边等的情况

     所以需要文件写完后需要关闭文件然后重新打开文件,让文件流指针指向文件开始位置让变下次的文件读操作

结果

9、复位文件流指针

形式:rewind(文件指针);
功能;把文件内部的位置指针移到文件开始位置
void test01()
{
    char buf[128] ="";
    char *path = "a.txt";

    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"w+");
    if(fp == NULL)
    {
        perror("fopen");
        return;
    }
    //先往文件中写入一个字符串"hello file"
    fputs("hello file",fp);
    //复位文件流指针
    rewind(fp); 
    
    //在从文件找那个读取该字符串    
    fgets(buf,sizeof(buf),fp);
    printf("buf = %s\n",buf);        
    //3、 关闭文件
    fclose(fp);
}

10、获得文件流指针距离文件首部的字节数

形式:ftell(文件指针);
返回值:返回当前位置(距离文件起始位置的字节数),出错返回-1
void test01()
{
    char buf[128] = "";
    char *path = "a.txt";

    long file_len = 0;
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"w+");
    if(fp == NULL)
    {
        perror("fopen");
        return;
    }
    //先往文件中写入一个字符串"hello file"
    fputs("hello file",fp);
    //获取文件流指针距离文件首部的字节数
    file_len = ftell(fp);
    printf("file_len = %ld\n",file_len);            
    //3、关闭文件
    fclose(fp);
}

11、定位文件的流指针 fseek函数

形式:fseek(文件类型指针,位移量,起始点);	//一般用于二进制文件
功能:移动文件中位置指针的位置
参数说明:
    位移量:相对 起始点 的偏移量,向前、向后移动的字节数(-10往左边移动10字节,+10往右边移动10字节)
    起始点:开始添加偏移 位移量 的位置
    位置指针的位置说明:
        在文件开头:0		(SEEK_SET)
        在文件当前位置:1	(SEEK_CUR)
        在文件末尾:2		(SEEK_END)

一次性读取文件总数

void test01()
{
    char *file_data = NULL;
    long file_len = 0;
    char *path = "a.txt";

    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"r");
    if(fp == NULL)
    {
        perror("fopen");
        return ;
    }
    //需求:一次性的将文件数据读取到内存中
    //1、得到文件的总大小
    //a、 使用 fseek 将文件指针定位到文件尾部
    fseek(fp,0,2);
    //b、使用 ftell 计算文件的偏移量==文件的总大小
    file_len = ftell(fp);
    //c、使用rewind复位文件流指针
    rewind(fp);
    //2、根据文件的总大小合理申请内存空间
    file_data = (char *)calloc(1,file_len+1);    //+1的目的 内存末尾存放'\0' 
    if(file_data == NULL)
    {
        fclose(fp);
        return;
    }
    //3、一次性将文件数据读入到内存空间
    fread(file_data,file_len,1,fp);
    //4、遍历读取到的文件内容
    printf("file_len = %ld\n",file_len);
    printf("%s\n",file_data);
    //5、释放堆区空间
    if(file_len != NULL)
    {
        free(file_len);
        file_len = NULL;
    }    
    // 关闭文件
    fclose(fp);
}

知识点九:feof()函数判断文件是否到达文件末尾

EOF宏:只能用于文本文文件

feof函数:可以用于文本文文件 二进制文件

判断文件是否结束:0:未结束,非0:表示结束

void test01()
{    
    char *path = "a.txt";
    int i = 0;
    FILE *fp = NULL;
    //1、 使用fopen打开一个文件获得文件指针
    fp = fopen(path,"r");
    if(fp == NULL)
    {
        perror("fopen");
        return ;
    }
    //feof(fp)判断文件是否结束 0:未结束,非 0:表示结束
    //while(feof(fp) == 0)//文件未结束才循环
    while( !feof(fp))
    {
        char ch = fgetc(fp);
        printf("%c",ch);
    }
    // 关闭文件
    fclose(fp);
}

知识点十:文件加密器

加密过程:

加密过程

解密过程:

解密过程
  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星仔_X

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值