目录
- 八、文件
1、行缓冲
2、全缓冲
3、无缓冲
4、文件指针
5、打开文件
6、关闭文件
7、一次读写一个字符
8、一次读写一个字符串(不适用于图片,只适用于文本)
9、读文件fread、写文件fwrite
10、格式化读写文件函数
11、随机读写(任意位置读写)
- 八、文件
1、行缓冲
标准io库函数往屏幕输出东西的时候是有行缓冲的,只有遇到换行符的时候才刷新缓冲区;以下情况刷新缓冲区:
a、缓冲区里有换行符:printf("hello world");while(1); 不输出
printf("hello world\n");while(1); ");while(1); 能输出
b、缓冲区满了,刷新缓冲区:whlie(1){printf("hello world"}; 能输出
c、认为刷新缓冲区:printf("hello world");fflush(stdout);while(1); 输出
d、程序正常结束会刷新缓冲区
2、全缓冲
标准io库函数,往普通文件读写数据都存在全缓冲,碰到换行符也不刷新缓冲区;缓冲区满了、人为使用fflush刷新或者程序正常结束时才会刷新缓冲区
3、无缓冲
在读写文件的时候通过系统调用 io (read write),对文件进行读写数据这个时候是无缓冲的, 即写数据会立马进入文件, 读数据会立马进入内存
4、文件指针
FILE * 指针变量标识符;
FILE 为大写, 需要包含<stdio.h>;FILE 是系统使用 typedef 定义出来的有关文件信息的一种结构体类型, 结构中含有文件名、 文件状态和文件当前位置等信息;一般情况下, 我们操作文件前必须定义一个文件指针标示 我们将要操作的文件;实际编程中使用库函数操作文件, 无需关心 FILE 结构体的细节 , 只需要将文件指针传给 io 库函数,库函数再通过 FILE 结构体里的信息对文件进行操作
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;
对文件操作的步骤:
①、对文件进行读写等操作之前要打开文件得到文件指针
②、可以通过文件指针对文件进行读写等操作
③、读写等操作完毕后, 要关闭文件, 关闭文件后, 就不能再通过此文件指针操作文件了
c 语言中有三个特殊的文件指针无需定义, 在程序中可以直接使用
stdin: 标准输入 默认为当前终端(键盘)
我们使用的 scanf、 getchar 函数默认从此终端获得数据
stdout: 标准输出 默认为当前终端(屏幕)
我们使用的 printf、 puts 函数默认输出信息到此终端
stderr: 标准错误输出设备文件 默认为当前终端(屏幕)
当我们程序出错使用:perror 函数时信息打印在此终端
5、打开文件
FILE *fopen(const char *path, const char *mode);
参数 1:打开的文件的路径
a、 绝对路径,从根目录开始的路径名称
“/home/edu/test/test.txt”
b、 相对路径
“./test/test.txt” 当前目录
“../test/test.txt” 父级目录
参数 2: 文件打开的方式, 即以什么样的方式(只读、 只写、 可读可写等等) 打开文件
模式 | 功能 |
r或rb | 以只读方式创建一个文本文件(不创建文件) |
w或wb | 以写方式打开文件(使文件长度截断为0字节,创建一个文件) |
a或ab | 以添加方式打开文件,即在末尾添加内容,当文件不存在时,创建文件用于写 |
r+或rb+ | 以可读、可写的方式打开文件(不创建新文件) |
w+或wb+ | 以可读、可写的方式打开文件(使文件长度为0字节,创建一个文件) |
a+或ab+ | 以添加方式打开文件,打开文件并在文件末尾更改文件(如果文件不存在,则创建文件) |
6、关闭文件
int fclose(FILE *fp);
关闭 fp 所代表的文件;一个文件只能关闭一次, 不能多次关闭。 关闭文件之后就不能再文件指针对文件进行读写等操作了。
成功返回 0;失败返回非 0
7、一次读写一个字符
int fgetc(FILE *stream); //fgetc 从 stream 所标示的文件中读取一个字节, 将字节值返回
返回值:
以 t 的方式: 读到文件结尾返回 EOF 适用于文本文件
以 b 的方式: 读到文件结尾, 使用 feof(后面会讲)判断结尾 适用于所有文件feof(fp) 到文件结尾返回非零值
int fputc(int c, FILE *stream); //fputc 将 c 的值写到 stream 所代表的文件中
返回值:
如果输出成功, 则返回输出的字节值;
如果输出失败, 则返回一个 EOF。
EOF 是在 stdio.h 文件中定义的符号常量, 值为-1
打开文件的时候, 默认读写位置在文件的开始, 如果以 a 的方式打开读写位置在文件的末尾
向文件中读取字节或写入字节的时候, 读写位置会往文件的末尾方向偏移, 读写多少个字节, 读写位置就往文件的末尾方向偏移多少个字节
8、一次读写一个字符串(不适用于图片,只适用于文本)
char *fgets(char *s, int size, FILE *stream);
从 stream 所指的文件中读取字符, 在读取的时候碰到换行符或者是碰到文件的末尾停止读取,或者是读取了 size-1 个字节停止读取, 在读取的内容后面会加一个\0,作为字符串的结尾;size足够大时可认为就是读取一行的函数
成功返回目的数组的首地址, 即 s; 失败返回 NULL
int fputs(const char *s, FILE *stream);
将 s 指向的字符串, 写到 stream 所代表的文件中
成功返回写入的字节数; 失败返回 -1
9、读文件fread、写文件fwrite
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
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
fwrite 函数将 ptr 指向的内存里的数据, 向 stream 所标示的文件中写入数据, 一块是 size 个字节, 共 nmemb块。
返回实际写入的块数
fwrite 函数是将内存中的数据原样输出到文件中。
fread 函数是将文件中的数据原样读取到内存里。
10、格式化读写文件函数
fprintf ( 文件指针, 格式字符串, 输出表列) ;
fscanf ( 文件指针, 格式字符串, 输入表列) ;
上面两个函数的使用和printf、scanf类似,只不过是将屏幕和键盘换成了文件
#include <stdio.h>
int main(void)
{
FILE *fp;
char ch1='a',ch2;
int num1=50,num2;
char string1[20]="hello",string2[20];
float score1=85.5,score2;
if((fp=fopen("test.txt","wb+"))==NULL)
{
printf("Cannot open the file\n");
return 0;
}
fprintf(fp,"%c %d %s %f\n",ch1,num1,string1,score1);
rewind(fp);
fscanf(fp,"%c %d %s %f\n",&ch2,&num2,&string2,&score2);
printf("%c %d %s %f\n",ch2,num2,string2,score2);
fclose(fp);
return 0;
}
printf:将内存数据结构格式化成字符串,输出到标准输出
sprintf:将内存数据结构格式化成字符串,输出到目标内存
fprintf:将内存数据结构格式化成字符串,输出到目标文件
scanf:将标准输入的字符串,格式化成数据结构存储到指定内存
sscanf:将指定内存的字符串,格式化成数据结构存储到指定内存
scanf:将指定文件的字符串,格式化成数据结构存储到指定内存
11、随机读写(任意位置读写)
移动文件内部的位置指针到需要读写的位置, 再进行读写, 这种读写称为随机读写;实现随机读写的关键是要按要求移动位置指针, 这称为文件的定位
void rewind(文件指针); 复位读写位置 把文件内部的位置指针移到文件首
long ftell(文件指针); 测文件读写位置距文件开始有多少个字节;取得文件流目前的读写位置;返回当前读写位置(距离文件起始的字节数), 出错时返回-1.
int fseek(FILE *stream, long offset, int whence); fseek 函数(一般用于二进制文件即打开文件的方式需要带 b);定位位置指针(读写位置);移动文件流的读写位置.
whence 起始位置:文件开头 SEEK_SET 0
文件当前位置 SEEK_CUR 1
文件末尾 SEEK_END 2
offset 位移量:以起始点为基点, 向前、 后移动的字节数, 正数往文件末尾方向偏移, 负数往文件开头方向偏移。