目录
1. 有关文件相关概念的概述
1.1 为什么我们需要文件
一般来讲,我们写代码所使用的数据均来自于数据库,但是数据在内存中的保存不会持久,当程序的运行结束时,数据便会丢失.
1.2 文件的简要分类
文件可分为程序文件与数据文件
程序文件一般以 .exe .obj .c作为后缀
数据文件便是读取数据的文件,这个文件是本文的重点讨论对象
二进制文件与文本文件都属于数据文件
1.2.1 二进制文件与文本文件对一个数据存储的区别
以10000为例
10000的二进制是 "00000000 00000000 100111 00010000"
下面是数据文件和文本文件存储上述二进制的10000的方式
a.文本文件
文本文件会将10000的四个数"1", "0", "0", "0", "0"这四个数字分别转换成ASCII码值的形式存储进入文本文件按
b.数据文件
数据文件将把10000的原码 "00000000 00000000 100111 00010000"转换成其补码形式存储进入数据文件
2. 文件的操作
我们一般使用程序对数据文件进行操作以达到预期的效果
文件的操作分为以下三个基础步骤
1.打开文件-> 2.读写文件-> 3.关闭文件
2.1 什么是流(stream)
流:指的是程序与外部设备交换信息的媒介,可以理解为信使
外部设备:屏幕,文件,网络等.
2.2 标准流(常用的流)
c语言程序在启动的时候会默认打开三个流
stdin:标准输出流,从键盘输入信息,scanf便是从此流读取数据.
stdout:标准输出流,输出至显示器,printf便是从此流读取数据.
stderr:标准错误流.
流的类型是FILE*
ps:FILE本身是一个结构体类型变量
2.3 文件指针
FILE是结构体类型的变量,由IDE定义;
此结构体适用于描述文件的一些1特征的,使用者不必去关心它的详细信息
在操作一个文件时,我们通常使用一个FILE*类型的指针作为一个stream去对文件进行各种操作
2.4 文件的打开与关闭
有关文件操作常用的字符
使用示例
以 'w' 为例进行文件的打开与关闭
int main1()
{
FILE* pf = fopen("data.txt", "w");//文件的打开,创建一个FILE*型的指针变量pf对文件进行操作
if (pf == NULL)
{
return 1;
}fclose(pf);//文件的关闭,用法有点类似于动态内存空间的释放
pf = NULL;
return 0;
}
上述例子是文件的打开与关闭,但凡对文件进行相关操作,上述框架必不可少
3.(重点)一些常用文件操作函数对文件进行顺序读写的使用
常用的文件操作函数
这一系列的函数头文件都是:#include <stdio.h>
3.1 fopen函数与fclose函数
函数参数:
int fclose ( FILE * stream );
FILE * fopen ( const char * filename, const char * mode );
见上文
3.2 fputc函数
函数参数:int fputc ( int character, FILE * stream );
函数作用:将字符串写入函数
fputc末尾的' c'就是character,就是操作对象是字符
例子
int main2()
{
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
return 1;
}int i = 0;
for (i = 0; i < 26; i++)
{
fputc('a' + i, pf);
}fclose(pf);
pf = NULL;
return 0;
}
例子详解: fputc('a' + i, pf);
将'a'+i字符写入pf所指向的文件中去
运行结果:
3.3 fgetc函数
函数参数:int fgetc ( FILE * stream );
函数作用:将文件中的字符串依次读取
fgetc末尾的' c'就是character,就是操作对象是字符
例子
int main3()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
return 1;
}int i = 0;
for (i = 0; i < 26; i++)
{
int ch = fgetc(pf);
printf("%c ", ch);
}
fclose(pf);
pf = NULL;
return 0;
}
例子详解:int ch = fgetc(pf);
printf("%c ", ch);
将指针pf所指向的文件中的26个字符从文件中依次读取
运行结果:
3.4 fputs函数
函数参数:int fgetc ( FILE * stream );
函数作用:将文件中的字符串依次读取
fgetc末尾的' c'就是character,就是操作对象是字符
例子
int main()
{
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
return 1;
}fputs("abcdef", pf);
fclose(pf);
pf = NULL;
return 0;
}
例子详解: fputs("abcdef", pf);将字符串"abcdef"写入pf所指向的文件
运行结果:
3.5 fgets函数
这个函数的参数有点繁琐且奇葩,奇葩在它的第二个参数int num,以及它的类型是char*,因为它是一个对字符串中的字符进行操作的函数
函数参数:char * fgets ( char * str, int num, FILE * stream );
函数作用: 从stream所指向的文件的字符串中最多读取num-1个字符放入指针ptr所指向的文件
例子
int main()
{
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
return 1;
}char arr[20] = {0};
fgets(arr, 10, pf);
fputs(arr, stdout);fclose(pf);
pf = NULL;
return 0;
}
例子详解:fgets(arr, 10, pf);将pf所指向的文件中的9个字符写入arr数组
3.6 fprintf函数
函数参数: int fprintf ( FILE * stream, const char * format, ... );
函数作用: 将结构体成员变量被赋予的值写入文件
例子
struct stu
{
char name[20];
int age;
float score;
};
int main6()
{
struct stu s = { "zhangsan",20,90 };
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
return 0;
}
fclose(pf);
pf = NULL;return 0;
}
例子详解: fprintf(pf, "%s %d %f", s.name, s.age, s.score);将结构体成员变量s.name, s.age, s.score以%s %d %f的形式写入指针pf所指向的文件
运行结果
3.7 fscanf函数
函数参数: int fscanf ( FILE * stream, const char * format, ... );
函数作用:将目标对象"..."以各种类型输入stream所指向的文件
例子
struct stu
{
char name[20];
int age;
float score;
};
int main()
{
struct stu s = { "zhangsan",20,90 };
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
return 1;
}fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
fprintf(stdout, "%s %d %f", s.name, s.age, s.score);fclose(pf);
pf = NULL;return 0;
}
例子详解: fscanf(pf, "%s %d %f", s.name, s.age, s.score);就是将"s.name, s.age, s.score"这三个元素以"%s %d %f"的形式输入到指针pf所指向的文件中去
运行结果:
总结 fprintf 和 fscanf 函数用法,如果有函数 fprintf( a , b , c ) 和函数 fscanf( a , b , c),就是将 c 元素以 b 的形式写入 a 所指向的文件.
3.8 fwrite函数
函数参数: size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
函数作用:将count个且每个大小为sizeof()的元素写入stream指向的文件
注:这个函数是二进制的写
例子
struct stu
{
char name[20];
int age;
float score;
};
int main()
{
struct stu s = { "zhangsan",20,90 };
FILE* pf = fopen("data.txt","wb");
if (pf == NULL)
{
return 1;
}fwrite(&s, sizeof(s), 1, pf);
fclose(pf);
pf = NULL;
return 0;
}
例子详解: fwrite(&s, sizeof(s), 1, pf);将起始地址为&s,每个字符大小为sizeof(s)的1个元素写入pf所指向的文件. 运行结 果 因为这个函数是二进制的写 所以可能生成一些乱码
3.9 fread函数
函数参数: int fscanf ( FILE * stream, const char * format, ... );
函数作用: 将流stream中count
例子
struct stu
{
char name[20];
int age;
float score;
};
int main()
{
struct stu s = { "zhangsan",20,90 };
FILE* pf = fopen("data.txt","wb");
if (pf == NULL)
{
return 1;
}fread(&s, sizeof(s), 1, pf);
fclose(pf);
pf = NULL;return 0;
}
例子详解: fread(&s, sizeof(s), 1, pf); 将初始地址为&s,每个大小为sizeof(s)的1元素写入pf所指向的文件.
运行结果:
封面