学习一门语言,学会文件操作是十分必要的,如果没有学会文件操作,从某种角度上来说,就基本很难体现出这种语言的价值。C语言库函数为文件操作提供了丰富的库函数,接下来我们需要做的是学会使用这些库函数,在我看来学会这些库函数已经学会文件操作的一大半了,接下来我会根据自己的理解来解析一些常用的文件操作函数。
fopen函数
FILE *fopen(const char *path,const char *mode)//文件指针名=fopen(文件名,使用文件方式)
功能:打开一个文件,打开成功返回有效的文件地址,失败则返回NULL。
path表示文件路径
mode选择文件的打开方式:
r 以只读的方式打开文件
r+ 以可读写方式打开文件,该文件必须存在
rb+ 读写打开一个二进制文件,允许读写数据,该文件必须存在
rw+ 打开一个文本文件,允许读和写
w 打开只写文件,若文件存在则长度清为0,即文件内容会消失。若文件不存在则创建该文件。
w+ 打开可读写文件,若文件存在则文件长度清为0,即该文件内容会消失。文件不存在则创建该文件。
FILE *p =fopen(“E://1.txt”,”r”); if(p){ printf(“success\n”); }
只要fopen成功打开文件,使用完后一定要调用fclose关闭。fclose的参数就是fopen的返回值。
int fclose(FILE *p);
getc函数
int getc(FILE *stream);
getc的参数是fopen成功打开文件后返回的指针,getc的返回值是一个char,功能是以字节为单位读取文件内容。
文本文件最后的结束标识符是-1,也就是宏EOF,EOF不是文件的一部分内容,只是文件结束的标识。二进制文件的结束标识符则不一定是-1。
putc函数
int putc(char c,FILE *stream);
c是需要写入文件的字符,stream是fopen成功打开文件后返回的指针,功能是向文件写入一个指定的字符。
getc必须用r模式打开,putc必须用w模式打开,读和写一定要分清模式。
下面例子会展示通过getc和putc读写指定文件
//使用putc例程 int main(int argc, char **args){ FILE *p = fopen(args[1], "w+"); if (argc<2) return 0; if(p){ //指定写文件 while(1) { char c = getchar(); if (c == '\n') break; putc(c, p); } fclose(p); } return 0; }
//使用getc例程 int main(int argc, char **args){ FILE *p = fopen(args[1], "r"); if (argc<2) return 0; if (p){ //指定读文件 char c = getc(p); while(c != EOF){ printf("%c", c); c = getc(p); } getchar(); fclose(p); } return 0; }
fgets函数与fputs函数
int fputs(const char *str, FILE *stream);
返回值:该函数返回一个非负值,如果发生错误则返回 EOF(-1)。str:这是一个数组,包含了要写入的以空字符终止的字符序列。stream:指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符串的流
fgets从stream中读取数据,每次读取一行。读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋'\0'),如果文件中的该行,不足bufsize-1个字符,则读完该行就结束。如若该行(包括最后一个换行符)的字符数超过bufsize-1,则fgets只返回一个不完整的行,但是,缓冲区总是以NULL字符结尾,对fgets的下一次调用会继续读该行。函数成功将返回buf,失败或读到文件结尾返回NULL。
fputs向指定的文件写入一个字符串(不自动写入字符串结束标记符‘\0’)。成功写入一个字符串后,文件的位置指针会自动后移,函数返回值为非负整数;否则返回EOF(符号常量,其值为-1)。
int main(){ FILE *p = fopen("x.txt", "w"); FILE *p1 = fopen("1.txt", "r"); if (p){ while (!feof(p1)){ //只要没到文件结尾那么循环继续 char buf[1024] = { 0 }; fgets(buf, sizeof(buf), p1); //fgets(buf, sizeof(buf), stdin); if (!strncmp(buf, "exit", 4))//若str1与str2的前n个字符相同,则返回0;若s1大于s2,则返回大于0的值;若s1 小于s2,则返回小于0的值。 break; fputs(buf, p); } fclose(p); fclose(p1); } return 0; }
EOF与feof函数文件结尾
int feof(FILE *stream);
如果已经是文件结尾,feof函数返回true;EOF不属于文件内容,知识文件的结尾标识,而且也不要用-1直接代替EOF。只有文本文件才能通过EOF判断文件的结尾标识,对二进制文件EOF是无效的
fgets与fputs实现文件加密解密
#include<stdlib.h> #include<string.h> #include<stdio.h> FILE *f_mp4, *P1; void decode(char* s) { int len = 0; while (s[len]) { s[len]++; len++; } } void encode(char* s) { int len = 0; while (s[len]) { s[len]--; len--; } } int main(int argc, char **args) //通过命令行指定拷贝文件 { if (argc<4) return -1; f_mp4 = fopen(args[1], "r"); if (f_mp4 == NULL)return 0; P1 = fopen(args[2], "w"); if (P1 == NULL)return 0; while (!feof(f_mp4)) { char buf[1024] = { 0 }; fgets(buf, sizeof(buf), f_mp4); if (args[3][0] == '0')//如果成立则加密 encode(buf); else if (args[3][0] == '1')//如果成立就解密 decode(buf); fputs(buf, P1); } fclose(f_mp4); fclose(P1); }
超大文件排序
有时候会对超大文件进行排序,我们的方法是先把超大文件读取到数组里,然后在再使排序算法对其进行排序,在写入到文件里。
int main() { srand((unsigned int)time(NULL)); FILE *p = fopen("a.txt", "w"); if (p) { for (int i = 0; i < 1000; i++) { int seq = rand(); char buf[100] = { 0 }; sprintf(buf,"%d\n", seq); fputs(buf, p); } fclose(p); } FILE *p1 = fopen("a.txt","r"); int arry[100] = { 0 }; int index = 0; while (!feof(p1)) { char buf[1024] = { 0 }; fgets(buf, sizeof(buf), p1); arry[index] = atoi(buf);//把读出来的字符串转化为数组 index++; } bubble(arry, index); //排序算法,此处需要自己写排序算法 fclose(p1); }
fprintf与fscanf函数
fprintf格式化输出到一个流/文件中;函数原型为int fprintf( FILE *stream, const char *format, [ argument ]...),fprintf()函数根据指定的格式(format)向输出流(stream)写入数据(argument)。
fscanf函数原型为 int fscanf(FILE * stream, const char * format, [argument...]); 其功能为根据数据格式(format)从输入流(stream)中读入数据(存储到argument);与fgets的差别在于:fscanf遇到空格和换行时结束,注意空格时也结束,fgets遇到空格不结束。
//1.txt文件内容 //2+3= //56+90= int main(){ FILE *P = fopen("1.txt","r"); FILE *P1 = fopen("2.txt", "w"); while (!feof(P)) { int a = 0; char b = 0; int c = 0; fscanf(P,"%d%c%d=", &a, &b, &c);//fscanf是从一个文件中读取字符串,并转义 if (feof(P)) break; fprintf(P1, "%d%c%d=%d\n", a, b, c, (a + c));//fprintf和sprintf功能类似,只是目标是文件,而不是字符串 } fclose(P); fclose(P1); }
//本例子主要是读取文件里的年龄 /*************txt文件内容***************** 年龄=15 年龄=89 年龄=23 ****************************************/ int main(){ FILE *p = fopen("1.txt", "r"); while (!feof(p)) { int age = 0; char buf[100]; fgets(buf, sizeof(buf), p); sscanf(buf, "年龄=%d", &age);//sscanf是从一个字符串中读取字符串,并转义 printf("%d\n", age); } getchar(); fclose(p); }