c语言学习之基础知识点介绍(十六):文件操作
一、文件的分类
1、文本文件:打开之后能看得懂的文件
2、二进制文件:打开之后看不懂,类似乱码之类的文件(视频,音频打开之后,能看、听,是应为电脑中装有播放器,播放器中含有解码器)。
二、操作文件的步骤和方式
操作步骤:
1、打开文件
2、操作文件
3、关闭文件
操作方式:
文件流:操作文件就像水流一样,将一个大的文件分成一段一段的流过去。
好处:分段操作,避免出现阻塞,卡死的发生。
三、操作文件的函数
1、fopen函数:
/* fopen函数: fopen(路径,操作方式); fopen("/Users/ios/Desktop/1.txt", "r"); 绝对路径:文件的全路径 相对路径:相对于当前文件所在的路径 r: 以只读的方式打开文件,如果文件存在,返回文件的指针,如果不存在返回NULL w: 以只写的方式打开文件,覆盖原文件再返回文件指针,如果不存在则创建再返回文件指针 a: 以追加的方式打开文件,如果文件存在,则追加原来的文件内容,如果不存在则创建文件。不管存在不存在最终都会返回文件指针 r+:功能和r还是一样,只不过增加了写的功能 w+:功能和w还是一样,只不过增加了读的功能 a+:功能和a还是一样,只不过增加了读的功能 以下不能单独用,要跟上面的嵌套一起 t: 代表操作的是文本文件 (默认的) rt wt at rt+ wt+ at+ b: 代表操作的是二进制文件 rb wb ab rb+ wb+ ab+ 在mac或者Linux或者UNIX下,t和b没有区别。 \n 在windows下有区别 \r\n 区别就在于,如果你在windows下面,写入的是文本文件,那么会把所有的换行或者说所有的\n替换成\r\n,二进制不会替换。 在mac或者Linux或者UNIX下,无论写入文本文件还是二进制文件,\n都不会做任何替换。 文件指针就叫 FILE指针。 注意:四个字都要大写。 用r打开,文件不存在返回NULL(0). 注意:NULL 就是 0 16进制0x0 如果不存在,就不能读取里面的内容,所以我们在读取之前应该判断是否不为NULL . */ #include <stdio.h> #include <string.h>int main(int argc, const char * argv[]) { FILE *fp; //变量名叫fp 是FILE指针 fp = fopen("/Users/ios/Desktop/1.txt", "r"); //FILE *fp = fopen("/Users/ios/Desktop/1.txt", "r"); fclose(fp); return 0; }
2、fgetc函数
/* fgetc函数: 用法:fgetc(文件指针); 作用:读取一个字符。 返回值读取到的字符。 例:char ch = fgetc(fp); 如果文件读取到末尾会读取到一个特殊字符叫 EOF,所以如果读取到EOF了,那么代表结束了。 EOF就是文件结束的标识符,读取到EOF就代表文件读取完了。 fputc: 语法:fputc(要写入的字符,文件指针); 作用:写入一个字符到文件 */ #include <stdio.h> #include <string.h> void readFile(){ FILE *fp; //假设文件内容为 abc fp = fopen("/Users/ios/Desktop/1.txt", "r"); if (fp != NULL) { //需要判断文件指针不为NULL才能操作 //操作 /* char ch = fgetc(fp); printf("%c\n",ch); //a char ch2 = fgetc(fp); printf("%c\n",ch2); //b char ch3 = fgetc(fp); printf("%c\n",ch3); //c */ while (1) { //因为不知道文件有多少字符,所以死循环 char ch = fgetc(fp); //读取字符· if (ch == EOF) { //判断读取的字符是不是文件末尾 break; //如果是则退出循环 } printf("%c",ch); //否则打印出读取到的内容 } fclose(fp); //一定要加fclose } } int main(int argc, const char * argv[]) { return 0; }
3、fputc函数
/* fputc: 语法:fputc(要写入的字符,文件指针); 作用:写入一个字符到文件。 */ void writeFile(){ FILE *fp = fopen("/Users/ios001/Desktop/1.txt", "w"); //写 if(fp != NULL ){ char str[] = "hello";//数组长度为6 int len = strlen(str); //计算字符串实际长度 只能算得5 for (int i = 0; i<len; i++) { //循环打印每个字符 fputc(str[i], fp); //str[0],str[1],str[2],str[3],str[4] } //操作文件 /* fputc('h', fp); fputc('e', fp); fputc('l', fp); fputc('l', fp); fputc('o', fp); */ //操作完成的提示 printf("结束!"); //关闭 fclose(fp);//只有在关闭之后,文件中才会有写入的文本。 } } int main(int argc, const char * argv[]) { FILE *fp = fopen("/Users/ios/Desktop/1.txt", "a"); //追加 if(fp != NULL ){ char str[] = " shanghai";//数组长度为8 int len = strlen(str); //计算字符串实际长度 只能算得5 for (int i = 0; i<len; i++) { //循环打印每个字符 fputc(str[i], fp); //str[0],str[1],str[2],str[3],str[4] } //操作文件 /* fputc('h', fp); fputc('e', fp); fputc('l', fp); fputc('l', fp); fputc('o', fp); */ //操作完成的提示 printf("完成!"); //关闭 fclose(fp); } return 0; }
4、fputs和fgets函数
/* 之前用fgetc和fputc只能一个一个字符的读,或者写,没法一下子读取一串字符串 所以如果要用fgetc或者fputc必须循环读取 所以我们需要一种非常方便读取或者写入一串字符串的方法 fputs: fputs(字符串,文件指针); 作用:写入一串字符串 详解:把字符串写入到文件指针所指向的文件处 例:fputs("我爱上海陆家嘴", fp); fgets: fgets(char数组地址, n, 文件指针); 作用:读取一串字符串 详解:把读取的字符,存到哪个数组里面,n代表一次读取几个字符,去哪个文件读 注意:1、只能读到n-1个有效字符,因为还有一个字符帮你加'\0' 2、如果读取到换行(\n),那么会停止读取,然后把换行也读取来,并且在换行后面加\0 读取多行: 文件中的文本行数无法确定,所以需要一个循环(死循环)。 判断读取到末尾: feof(文件指针); 如果返回的是1(真),代表读取到末尾。 如果返回的是0,代表没有到末尾。 */ #include <stdio.h> /** * 写入一串字符串 */ void writeString(){ FILE *fp = fopen("/Users/ios/Desktop/1.txt", "w"); if(fp != NULL){ //写字符串 fputs("我爱家乡妹子多", fp); printf("写完了\n"); fclose(fp);//立即写不要忘关闭,不然内容不会保存 } } int main(int argc, const char * argv[]) { FILE *fp = fopen("/Users/ios001/Desktop/1.txt", "r"); if(fp != NULL){ char str[100]; //读 while (1) { if(feof(fp)){ //如果为真,代表读取到末尾 break; //不需要继续读了,退出循环 } fgets(str, 100, fp); printf("%s",str); } /* fgets(str, 100, fp); //因为你输入10,那么它只会读取99个有效的,还有一个位置是帮你加一个'\0' printf("%s\n",str); char str2[100]; fgets(str2, 100, fp); printf("%s\n",str2); */ fclose(fp);//关闭文件 } return 0; }
补充一点:上面的代码判断某个变量是否为NULL的时候 都是 if(fp != NULL){},其实也可以这样写,if(fp){},应为 NULL 就是 0,也就是假,当fp不为NULL的时候,就是真。
4、fread和fwirte函数
/* fgetc fputc fgets fputs:没有一段一段的读取文件 fread和fwrite就比较像文件流一样一块一块的读或者写 fread: fread(保存数据的地址,每块的字节大小,读取多少块,文件指针); 1、它是读取文件的,而且任何问题都可以读,而且是分块读取。 1)、因为任何文件都可以读,所以保存数据的地址是可以不同类型。 分块来读:所以要设置每块的字节大小,一共要读取多少块,去哪个文件读 例: char str[50]; fread(str, 3, 100, fp); 注意:它只关心具体读的字节数,不会关心这些自己里面有没有换行 fwrite: fwrite(写入的数据,每块的字节大小,写入多少块,文件指针); 它是写入文件的。是分块写入。 第一个是告诉系统,写入什么数据,第二个是告诉系统每块多少字节,第三个是告诉系统分多少块写入,第四个是写入到哪个文件 注意:fwrite不要写的太大,要以实际为准,否则会写很多垃圾的二进制值进去,就打不开了 数组名 == &数组名 */ #include <stdio.h> #include <string.h> void testFread(){ FILE *fp = fopen("/Users/ios/Desktop/1.txt", "r"); if(fp){ //操作 while (1) { //读取大文件时最好分很多段读取,这样可以有效节省内存,所以用循环 if(feof(fp)){ break; } char str[50] = {0}; fread(str, 3, 3, fp); printf("%s",str); } fclose(fp); } } void testFwrite(){ FILE *fp = fopen("/Users/ios/Desktop/1.txt", "w"); if(fp){ /* char str[] = "好就按我说结婚的撒娇看到过撒娇吧"; int len = strlen(str); fwrite(str, 1, len, fp); */ // int num = 97; // // fwrite(&num, 4, 1, fp); // char ch = 'a'; // // fwrite(&ch, 1, 1, fp); char str[] = "10.333"; fwrite(str, 1,strlen(str), fp); printf("成功了\n"); fclose(fp); } } int main(int argc, const char * argv[]) { FILE *fp = fopen("/Users/ios/Desktop/1.txt", "r"); if(fp){ int num;//存的是二进制,打开后会转成十进制的ascii fread(&num, 4, 1, fp); printf("%d\n",num); fclose(fp); } return 0; }
4、fprintf和fscanf函数
/* printf:输出到控制台 scanf: 从控制台输入 scanf("格式化控制符",地址列表); fprintf:输出到文件(写入到文件) fprintf(文件指针,"格式化控制符",参数列表); fscanf:从文件输入(读取) fscanf(文件指针,"格式化控制符",地址列表); */ #include <stdio.h> void testFprintf(){ FILE * fp = fopen("/Users/ios/Desktop/1.txt", "w"); if (fp) { fprintf(fp, "%d",99); fclose(fp); } } int main(int argc, const char * argv[]) { fprintf(stdout, "哈哈哈哈哈\n"); //跟printf没差别,stdout代表在控制台输出 int num; fscanf(stdin, "%d",&num); //stdin在控制台输入 printf("num=%d\n",num); /* FILE * fp = fopen("/Users/ios/Desktop/1.txt", "r"); if (fp) { // int num; // char ch; // fscanf(fp, "%c帅%d",&ch,&num); // printf("ch=%c num=%d\n",ch,num);//a 99 char str[50] = {0}; char str2[50]; fscanf(fp, "%s\n%s",str,str2); puts(str); puts(str2); fclose(fp); } */ return 0; }
四、文件的复制
/* //加密: //读取出来以后对每个字节做一个-1的操作 //然后再写,就达到加密的作用了 //解密: //先读出的加密,然后对每个字节进行+1的操作,然后再写,此时就可以看了 */ #include <stdio.h> int main(int argc, const char * argv[]) { //读取原文件 FILE *fpRead = fopen("/Users/ios/Movies/高清无码声音又好听的片.mp4","r"); //拷贝新的文件 FILE *fpWrite = fopen("/Users/ios/Desktop/123/工作文件不要看.mp4", "w"); if(fpRead){ if(fpWrite){ while(1){ if(feof(fpRead)){ break; } char bytes[1024*1024]; //1m //开始读 fread(bytes, 1024*1024, 1, fpRead); //开始写 fwrite(bytes, 1024*1024, 1, fpWrite);//写入到这个文件 } printf("做完了!\n"); fclose(fpWrite); } fclose(fpRead); } return 0; }