C语言文件常用操作
一、FILE结构体
FILE *fp = fopen("YKDog.txt", "r");
FILE 是一个结构体。文件是存放在物理磁盘上的,包括文件控制块(FCB)
和数据块
。文件控制块通常包括文件权限、日期(创建、读取、修改)、拥有者、文件大小、数据块信息。数据块用来存储实际的内容。对于打开的文件,操作系统是这样管理的:
系统维护了两张表,一张是系统级打开文件表,一张是进程级打开文件表(每个进程有一个)
我们不能直接操作系统级的文件表, 所以我们可以通过进程级文件表指针间接操作FCB
。FILE结构体中的_file指针指向了进程级文件表, 而进程级文件表保存了指向系统级文件表的指针和其他信息。简而言之,操作FILE结构体,就间接的操作了文件。而操作FILE结构体, 我们采用了FILE *fp这个指针。
二、fopen函数
FILE *fp = fopen(文件路径,操作权限)
权限设置如下:
权限字符 | 含义 |
---|---|
r | 如果路径文件不存在就会返回NULL,不存在不会创建文件。 |
r+ | 不存在报错并且不会创建 |
w | 如果文件不存在不会返回NULL,并且会创建文件 |
a | 如果文件不存在不会报错, 并且会自动创建文件 |
a+ | 如果文件不存在不会报错自动创建, 在末尾追加不会覆盖 |
w+ | 不存在不会返回NULL报错, 自动创建,会清空后覆盖 |
二、fputc和fgetc函数
fputc返回值是写入成功的字符,如果写入失败返回EOF(-1的一个宏, end of file缩写)
fputc(字符, FILE*)
fgetc(FILE*)返回一个读到的字符, 结尾或出错(比如权限不够)返回EOF
看一个练习就知道怎么用了
练习:写入a-z的字符到YKDog.txt中,再用fgetc读取
code
FILE *fp = fopen("YKDog.txt", "w");
//路径 + 写权限
if (fp == NULL) printf("error");
for(char i = 'a'; i <= 'z'; i++){
printf("%-3c", fputc(i, fp));
//返回值是写入成功的字符
}
printf("\n");
fclose(fp);
FILE *fpr = fopen("YKDog.txt", "r");
if (fp == NULL) printf("error");
char ch;
while((ch = fgetc(fp)) != EOF){
printf("%-3c", ch);
}
fclose(fpr);
结果:
a b c d e f g h i j k l m n o p q r s t u v w x y z
a b c d e f g h i j k l m n o p q r s t u v w x y z
要特别注意的是写完一定要fclose不然不会把缓存中的数据写到磁盘上, 导致下边的读取出问题。
返回值总结:fputc 返回值是写入成功的字符,失败返回EOF。fgetc返回值是读取到的字符,失败或结束返回EOF
三、feof判断文件流结束标识函数
函数避免使用
feof如果到结束标识就返回1, 否则返回1.
练习使用fgetc获得之前YKDog中的a-z
易错思路:
如果没有遇到结束标识就一直打印。刚好结束就不执行while中语句了。然而忽略了这个延迟, 标志位要到下一次读取(fgetc)的时候才会修改为1.下一次读取, 已经超出范围。
FILE *fp = fopen("YKDog.txt", "r");
if (fp == NULL) printf("error");
while(!feof(fp)){
printf("%c ", fgetc(fp));
}
fclose(fp);
a b c d e f g h i j k l m n o p q r s t u v w x y z ?
修改思路,既然延迟一个读写修改结束单位。那我就多读取一次
FILE *fp = fopen("YKDog.txt", "r");
if (fp == NULL) printf("error");
char ch = fgetc(fp);
while(!feof(fp)){
printf("%c ",ch );
ch = fgetc(fp);
}
fclose(fp);
四、fputs和fgets
fputs 是写一个字符串到文件中。
fpusts(字符串首地址, FILE *) 返回值是 如果写入成功返回0 或字符串的长度(平台不一样结果不一, 肯定是非负), 失败返回EOF.\n等字符也会写入。并且自动加上\0
FILE *fp = fopen("YKPig.txt", "w");
if(fp == NULL) printf("error");
int ret=fputs("Hello, YKPig\n", fp);
printf("ret = %d\n", ret);
有的操作系统比如centOS, MacOS会在文本编辑结束后会自动在其后加入\n也就是0a。windows不会
fgets(buf, 10, FILE *fpr)
简单的说吧, 把fpr文件内容每次10-1个字节读入到buf中。如果遇到\n或者文件结束 结束读取。每读取一次在内容后自动添加\0。
返回值是每次成功读到的 保存到buf中字符的首个地址。失败返回NULL
总结:
fgets 函数返回有三个条件:
- 读 n-1 个字符前遇到\n,读取结束。
- 读 n-1 个字符前遇到 EOF,读取结束。
- 最多读 n-1 个符。
- 在每读一行后自动加’\0’。
Mac下读内容
.表示\n换行。最后一个是系统加的
FILE *fpr = fopen("YKBird.txt", "r");
if (fpr == NULL) printf("error");
char buf[1024];
while(fgets(buf, 10, fpr) !=NULL ){
printf("%s=", buf);
}
结果
123456789=abcdefg
=123456789=0
=abcdefg
=
注意:
- 打印的时候是遇到\n才打印的。
- buff中不是存储所有的结果。是存储每次读到的结果。