目录
文件概念
文件名
文件指针
文件的关闭和打开
打开方式:
fopen():打开文件
fclose():文件关闭
文件的顺序读写
写文件(fputc)
读文件(fgetc)
字符串读(fgets)
字符串写(fputs)
格式化写(fprintf)
格式化读(fscanf)
sprintf和sscanf
文件概念
在程序运行时,常常需要将一些数据(运行的最终结果和中间数据)输出到磁盘上存放起来,以后需要时再从磁盘中输入到计算机内存。这就要用到磁盘文件。
C语言把文件看作是一个字符(字节)的序列,即一个一个字符(字节)的数据顺序组成。根据数据的组织形式,可分为ASCII文件和二进制文件。ASCII文件又称文本文件,它的每一个字节放一个ASCII代码,代表一个字符。二进制文件是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。
在过去使用的C版本(如UNIX系统下使用的C)有两种对文件的处理方法:一种叫“缓冲文件系统”,一种叫“非缓冲文件系统”。所谓缓冲文件系统是指系统自动地在内存中为每一个正在使用的文件名开辟一个缓冲区。从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去。如果从磁盘向内存读入数据,则一次从磁盘文件将一批数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(给程序变量)。缓冲区的大小由各个具体的C版本确定,一般为512字节。
文件名
一个文件要有唯一的文件标识,以便用户识别和使用
文件名包括三部分,文件路径+文件名主干+文件后缀
例如:c:codetest.txt
文件指针
缓冲文件系统中,关键的概念是“文件指针”。每个被使用的文件都在内存中开辟一个区,用来存放文件的有关信息(如文件的名字、文件状态及文件当前位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统定义的,取名为FILE。
文件的关闭和打开
打开方式:
| 文件使用方式 | 含义 | 如果指定的文件不存在 |
|---|---|---|
| "r"(只读) | 为了输入数据,打开一个已存在的文本文件。 | 出错 |
| "w"(只写) | 为了输出数据,打开一个文本文件。 | 建立一个新文件 |
| "a"(追加) | 向文本文件尾添加数据 | 出错 |
| "rb"(只读) | 为了输入数据,打开一个二进制文件。 | 出错 |
| "wb"(只写) | 为了输出数据,打开一个二进制文件。 | 建立一个新文件 |
| "ab"(追加) | 向二进制文件尾添加数据 | 出错 |
| "r+"(读写) | 为了读和写,打开一个文本文件 | 出错 |
| "w+"(读写) | 为了读和写,建立一个新的文件 | 建立一个新文件 |
| "a+"(读写) | 打开一个文件,在文件尾进行读写 | 建立一个新文件 |
| "rb+"(读写) | 为了读和写,打开一个二进制文件 | 出错 |
| "wb+"(读写) | 为了读和写,新建一个新的二进制文件 | 建立一个新文件 |
| "ab+"(读写) | 打开一个二进制文件,在文件尾进行读和写 | 建立一个新的文件 |
fopen():打开文件
fopen():文件打开操作
头文件:stdio.h
函数定义:FILE *fopen(char *pname, char *mode)
函数说明:pname是文件名,mode是打开文件的方式
#includeint main() { fopen("test.txt", "r"); return 0; }
打开文件的作用是:
(1)分配给打开文件一个FILE 类型的文件结构体变量,并将有关信息填入文件结构体变量;
(2)开辟一个缓冲区;
(3)调用操作系统提供的打开文件或建立新文件功能,打开或建立指定文件;
FILE *:指出fopen是一个返回文件类型的指针函数;返回值
正常返回:被打开文件的文件指针。
异常返回:NULL,表示打开操作不成功。
关闭:
fclose():文件关闭
函数定义:int fclose(FILE *fp);
函数说明:fp是一个以打开的文件的文件指针
返回值:
正常返回:0
异常返回:EOF,表示文件在关闭时发生错误
文件的顺序读写
| 功能 | 函数名 | 适用于 |
|---|---|---|
| 字符输入函数 | fgetc | 所有输入流 |
| 字符输出函数 | fputc | 所有输出流 |
| 文本行输入函数 | fgets | 所有输入流 |
| 文本行输出函数 | fputs | 所有输出流 |
| 格式化输入函数 | fscanf | 所有输入流 |
| 格式化输出函数 | fprintf | 所有输出流 |
| 二进制输入 | fread | 文件 |
| 二进制输出 | fwrite | 文件 |
写文件(fputc)
描述
C 库函数 int fputc(int char, FILE *stream) 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。
声明
下面是 fputc() 函数的声明。
int fputc(int char, FILE *stream) 参数
- char -- 这是要被写入的字符。该字符以其对应的 int 值进行传递。
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符的流。
返回值:
如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF,并设置错误标识符。
#include#include int main() { FILE*pf=fopen("test.txt", "w"); if (pf == NULL) { printf("%sn", strerror(errno)); return 0; } fputc('b', pf); fputc('i', pf); fputc('t', pf); fclose(pf); return 0; }
读文件(fgetc)
描述
C 库函数 int fgetc(FILE *stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。
声明
下面是 fgetc() 函数的声明。
int fgetc(FILE *stream)
参数
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了要在上面执行操作的流。
返回值
该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。
#include#include int main() { FILE*pf=fopen("test.txt", "r"); if (pf == NULL) { printf("%sn", strerror(errno)); return 0; } printf("%c", fgetc(pf)); printf("%c", fgetc(pf)); printf("%c", fgetc(pf)); fclose(pf); return 0; }
键盘-——标准输入设备——stdin
屏幕——标准输出设备——stdout
是一个程序默认打开的两个流设备
int main()
{
int ch=fgetc(stdin);//从键盘上输入
fputc(ch,stdout);//从屏幕上输出
return 0;
}
字符串读(fgets)
描述
C 库函数 char *fgets(char *str, int n, FILE *stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
声明
下面是 fgets() 函数的声明。
char *fgets(char *str, int n, FILE *stream)
参数
- str -- 这是指向一个字符数组的指针,该数组存储了要读取的字符串。
- n -- 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。
返回值
如果成功,该函数返回相同的 str 参数。如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。
如果发生错误,返回一个空指针。
int main()
{
char buf[1024] = { 0 };
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
return 0;
}
fgets(buf, 1024, pf);
printf("%s", buf);
fclose(pf);
pf = NULL;
return 0;
}
字符串写(fputs)
描述
C 库函数 int fputs(const char *str, FILE *stream) 把字符串写入到指定的流 stream 中,但不包括空字符。
声明
下面是 fputs() 函数的声明。
int fputs(const char *str, FILE *stream)
参数
- str -- 这是一个数组,包含了要写入的以空字符终止的字符序列。
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符串的流。
返回值
该函数返回一个非负值,如果发生错误则返回 EOF。
int main()
{
char buf[1024] = { 0 };
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
return 0;
}
fputs("hellow", pf);
fgets(buf, 1024, pf);
pf = NULL;
return 0;
}
int main()
{
char buf[1024] = { 0 };
FILE* pf = fopen("test.txt", "w");
fgets(buf, 1024, stdin);//从标准输入流读取
fputs(buf, stdout);//输出到标准输出流
return 0;
}
上面代码可以等价于
int main()
{
char buf[1024] = { 0 };
FILE* pf = fopen("test.txt", "w");
gets(buf);
puts(buf);
return 0;
}
格式化写(fprintf)
int main()
{
int a = 111;
FILE* pf = fopen("test.txt", "w");
fprintf(pf, "%d", a);
return 0;
}
注释:把a写到文件里面
格式化读(fscanf)
struct S
{
int n;
float score;
char arr[10];
};
int main()
{
struct S s = { 0 };
FILE* pf = fopen("test.txt", "w");
fscanf(pf, "%d %f %s", &(s.n), &(s.score), s.arr);
return 0;
}
注释:把信息从文件里面读到结构体里面
比较
scanf( "%d %f %s", &(s.n), &(s.score), s.arr); //相当于 fscanf(stdin, "%d %f %s", &(s.n), &(s.score), s.arr); fprintf(stdout, "%d %f %s", s.n, s.score, s.arr); //相当于 printf( "%d %f %s", s.n, s.score, s.arr);
sprintf和sscanf
sprintf
int main()
{
struct S s = { 100,3.14,"abcdef"};
char buf[1024] = { 0 };
sprintf(buf, "%d %f %s", s.n, s.score, s.arr);
return 0;
}
把结构体内容写到字符数组里面去。
sscanf
int main()
{
struct S s = { 100,3.14,"abcdef"};
struct S temp = { 0 };
char buf[1024] = { 0 };
sprintf(buf, "%d %f %s", s.n, s.score, s.arr);
sscanf(buf, "%d %f %s", &(temp.n), &(temp.score), temp.arr);
return 0;
}
把字符数组里面的内容读到结构体里面去。



