目录
一、为什么要使用文件
文件顾名思义就是用来保存一些数据;人的记忆能力是有限的, 以通讯录为例,它是用来存储联系人的相关信息的,如果你的人缘不是很好,就10个联系人,或许你能够全部记住;如果你认识的人很多有1000个,你要将这1000个人的信息存储起来,如果使我们来设计一款通讯录软件,如果只能存入数据,却不能保存数据,那么有谁敢用这款软件呢?
接下来就位大家介绍一下文件操作的实际用途:
二、什么是文件
1.程序文件
1. 源程序文件 --- .c文件
2. 目标文件 --- .obj文件(windows环境)
3. 可执行程序 --- .exe文件(windows环境)
2.数据文件
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容否认文件;
3.文件名
文件名包含3个部分:文件路径+文件主干+文件后缀
例如:c:\code\test.txt
三、文件的打开和关闭
1.文件流的概念介绍
流是一个高度抽象的概念,可以理解为水流,常说水往低处流,人往高处走;文件也是一样的,当我们要从电脑上读取某个文件的信息或者要将某些数据写入指定的文件中,那么这样的操作说明文件是流动的,参考下方图解:
2.文件指针
文件指针是已经被封装好的一个指针类型,当我们使用时,文件指针就指向了文件的起始位置,定义方式:
FILE* pf;//定义一个文件指针变量
3.fopen和fclose函数
fopen函数:
函数原型:FILE *fopen( const char *filename, const char *mode );
头 文 件:<stdio.h>
函数功能:打开文件
参数解读:
filename --- 要打开的文件名;
传给filename指针的两种形式:传相对路径和传绝对路径
相对路径:c:\code\test.txt 绝对路径:test.txt
mode --- 打开方式;
fclose函数:
函数原型:int fclose( FILE *stream );
头 文 件:<stdio.h>
函数功能:关闭文件
参数解读:stream --- 指向FILE结构的指针(关闭那个文件就传那个文件的指针)
4.打开方式介绍
文件使用方式
|
含义
|
如果指定文件不存在
|
---|---|---|
“r”
(只读)
|
为了输入数据,打开一个已经存在的文本文件
|
出错
|
“w”
(只写)
|
为了输出数据,打开一个文本文件
|
建立一个新的文件
|
“a”
(追加)
|
a”
(追加)向文本文件尾添加数据
|
建立一个新的文件
|
“rb”
(只读)
|
为了输入数据,打开一个二进制文件
|
出错
|
“wb”
(只写)
|
为了输出数据,打开一个二进制文件
|
建立一个新的文件
|
“ab”
(追加)
|
向一个二进制文件尾添加数据
|
出错
|
“r+”
(读写)
|
为了读和写,打开一个文本文件
|
出错
|
“w+”
(读写)
|
为了读和写,建议一个新的文件
|
建立一个新的文件
|
“a+”
(读写)
|
打开一个文件,在文件尾进行读写
|
建立一个新的文件
|
“rb+”
(读写)
|
为了读和写打开一个二进制文件
|
出错
|
“wb+”
(读写)
|
为了读和写,新建一个新的二进制文件
|
建立一个新的文件
|
“ab+”
(读写)
|
打开一个二进制文件,在文件尾进行读和写
|
建立一个新的文件
|
举例:
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "r");//只读
//data.txt(相对路径)
//C:\\Users\\MLG\\Desktop\\data.txt(这是绝对路径) 这是完整的路径 要将\转义一下
if (pf == NULL)
{
perror("fopen");
return -1;
}
/*
读文件的操作
.........
..........
*/
fclose(pf);//关闭文件
pf = NULL;
return 0;
}
四、文件的顺序读写
功能 | 函数名 | 适用于 |
---|---|---|
字符输入函数
|
fgetc
|
所有输入流
|
字符输出函数
|
fputc
|
所有输出流
|
文本行输入函数
|
fgets
|
所有输入流
|
文本行输出函数
|
fputs
|
所有输出流
|
格式化输入函数
|
fscanf
|
所有输入流
|
格式化输出函数
|
fprintf
|
所有输出流
|
二进制输入
|
fread
|
文件
|
二进制输出
|
fwrite
|
文件
|
1.fputc和fgetc函数
fputc函数:字符输出函数
函数原型:int fputc( int c, FILE *stream );
头 文 件: <stdio.h>
函数功能:一次完成一个字符的数书写;
举例:
把 'h' , 'e' , 'h' , 'e' 这四个字符写到文件中,再读到屏幕上;
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "w");
//w --- (我这是打开的桌面得到路径)w的意思就是如果桌面没有data.txt这个文件,就会主动创建一个data.txt
if (pf == NULL)
{
perror("fopen");
return -1;
}
fputc('h', pf);
fputc('e', pf);
fputc('h', pf);
fputc('e', pf);
fclose(pf);
pf = NULL;
return 0;
}
打开创建好的文件,查看是否将“hehe”输出/写到 data.txt文件中;
fgetc函数:字符输入函数
函数原型:int fgetc( FILE *stream );
头 文 件: <stdio.h>
函数功能:一次读一个字符;
举例:
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "r");//因为要读文件,这里打开方式用“r”
if (pf == NULL)
{
perror("fopen");
return -1;
}
int ch = fgetc(pf);
printf("%c\n", ch);//打印 h
ch = fgetc(pf);
printf("%c\n", ch);//打印 e
ch = fgetc(pf);
printf("%c\n", ch);//打印 h
ch = fgetc(pf);
printf("%c\n", ch);//打印 e
fclose(pf);
pf = NULL;
return 0;
}
2.fputs和fgets函数
fputs函数:文本行输出函数
函数原型:int fputs( const char *string, FILE *stream );
头 文 件: <stdio.h>
函数功能:写一行数据;
举例:
把"hello world"和"hello China"这两个字符串写到文件中,再打印到屏幕上;
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "w");
if (pf == NULL)
{
perror("fopen");
return -1;
}
fputs("hello world\n", pf);
fputs("hello China\n", pf);
fclose(pf);
pf = NULL;
return 0;
}
fgets函数:文本行输入函数
函数原型:char *fgets( char *string, int n, FILE *stream );
头 文 件: <stdio.h>
函数功能:读一行数据;
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return -1;
}
char arr[20] = { 0 };
fgets(arr, 8, pf);
// 从pf中读,一次读8个字符,读到arr里
// 这里的8表示最多读8个,只读7个,他会在第8个上放\0
printf("%s\n", arr);
fclose(pf);
pf = NULL;
return 0;
}
3.fprintf和fscanf函数
fprintf函数:格式化输出函数
函数原型:int fprintf( FILE *stream, const char *format [, argument ]...);
头 文 件: <stdio.h>
函数功能:等于printf,就多了一个文件指针
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "w");
if (pf == NULL)
{
perror("fopen");
return -1;
}
char arr[10] = "hello";
char ch = 'c';
//写文件
fprintf(pf, "%s\n", arr);
fprintf(pf, "%c", ch);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fscanf函数:格式化输入函数
函数原型:int fscanf( FILE *stream, const char *format [, argument ]... );
头 文 件: <stdio.h>
函数功能:等于scanf,就多了一个文件指针
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return -1;
}
char arr[10] = { 0 };
char ch = 0;
//读文件
fscanf(pf, "%s\n", arr);
fscanf(pf, "%c", &ch);
printf("%s\n", arr);
printf("%c", ch);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
4.fwrite和fread函数
fwrite函数:二进制输出函数
函数原型:size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
头 文 件: <stdio.h>
函数功能:以二进制的形式将数据写入;
参数解读:
1. buffer - 要被写的数据
2. size - 一个元素多少个字节
3. count - 写几个数据
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "wb");//二进制写
if (pf == NULL)
{
perror("fopen");
return -1;
}
int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
//写文件
fwrite(arr, sizeof(arr), 1, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
此时记事本中全部是看不懂的,是存储失败了?加密了?其实它只是以二进制的形式存储,我们看不懂很正常,只要我们能够以二进制的形式读取出来就说明保存没有出错;
fread函数:二进制输入函数
函数原型:size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
头 文 件: <stdio.h>
函数功能:以二进制的形式将数据读出来;
参数解读:
1. buffer - 数据的存储位置
2. size - 一个元素多少个字节
3. count - 要读取的个数
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "rb");//二进制读
if (pf == NULL)
{
perror("fopen");
return -1;
}
int arr[10] = { 0 };
//读文件
fread(arr, sizeof(arr), 1, pf);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
此时发现能够正常的打印出来,说明刚才在存储的时候是正确的,这里是不是可也给自己的小伙伴发一道密语,只有你们之间知道小秘密 ;
五、文件的随机读写
1.fseek函数
函数原型:int fseek( FILE *stream, long offset, int origin );
头 文 件: <stdio.h>
函数功能:根据文件指针的位置和偏移量来定位文件指针;
参数解读:
1. offset --- 偏移量
2. origin --- 起始位置3个
① SEEK_CUR --- 文件指针当前的位置
② SEEK_END --- 文件的末尾
③ SEEK_SET --- 文件的起始位置
文件在读取的时候,会自动指向已读完数据的下一个数据的地址;
2.ftell函数
函数原型:long ftell( FILE *stream );
头 文 件: <stdio.h>
函数功能:计算文件指针相对于起始位置的偏移量;
3.rewind函数
函数原型:void rewind( FILE *stream );
头 文 件: <stdio.h>
函数功能:让文件指针回到起始位置;
举例:
如果我们对文件中存储的abcdef进行随机读写,假设先读取一个字符d,再读取一个字符c最后计算读取结束后指针相对于起始位置的偏移量;
#include <stdio.h>
int main()
{
FILE* pf = fopen("C:\\Users\\MLG\\Desktop\\data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return -1;
}
//如果第一次就要读取一个d字符
fseek(pf, 3, SEEK_SET);
int ch = fgetc(pf);
printf("%c\n", ch);
//abcdef 当读完d后 文件指针当前的位置是指向e的
//当要读取c的时候,需要向后偏移2(即-2)
fseek(pf, -2, SEEK_CUR);
ch = fgetc(pf);
printf("%c\n", ch);
//计算文件指针相对于起始位置的偏移量
ch = ftell(pf);
printf("%d\n", ch);
//让文件指针回到起始位置
rewind(pf);
ch = fgetc(pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
扩展
文件读取结束的判定
feof --- 是文件读取结束了,判断是不是遇到文件末尾而结束的
ferror --- 文件读取结束考了,判断是不是遇到错误后读取结束