1、文件操作
int main(){ FILE *p=fopen("D:\temp\a.txt","w");//用写的方式打开一个文件 //w的意思是如果文件不存在就建立一个,如果文件存在就覆盖 fputs("hello world",p);//向文件中写入一个字符串 fclose(p);//关闭文件 }
int main(void){ char s[1024]={0}; FILE *p=fopen("D:\temp\a.txt"); while(1){ memset(s,0,sizeof(s)); gets(s);//gets可以接收空格 而scanf("%s",s);不可以 if(strcmp(s,"exit")==0){ break; } int len=strlen(s); s[len]=' ';//由于我们并不能将scanf中输入的换行显示在文本当中 所以要在每次输入完成字符串之后 按照每次输入的内容换行 fputs(s,p); } fclose(p); printf("end "); return 0; }
2、读文件
int main(){ char s[1024]={0}; FILE *p=fopen("D:\temp\a.txt","r"); //feof(p);如果已经到了文件结尾,feof函数返回真 while(!feof(p))//如果没有到文件结尾就一直循环 { memset(s,0,sizeof(s)); fgets(s,sizeof(s),p);//参数分别是内存地址 这块内存大小 fopen返回的文件指针 printf("%s",s); } fclose(p); return 0; }
3、文本文件加密
void code(char *s){ while(*s){ (*s)++; s++; } } void decode(char *s){ while(*s){ (*s)--; s++; } } int main(){ char s[1024]={0}; FILE *p=fopen("D:\temp\a.txt","r"); FILE *p1=fopen("D:\temp\b.txt","w"); while(!feof(p))//如果没有到文件结尾就一直循环 { memset(s,0,sizeof(s)); fgets(s,sizeof(s),p); code(s); fputs(s,p1); } fclose(p); fclose(p1); return 0; }
4、读写方式
r 以只读方式打开文件,该文件必须存在
r+ 以可读写方式打开文件,该文件必须存在
rb+ 读写打开一个二进制文件,允许读写数据,文件必须存在
rw+ 读写打开一个文本文件,允许读和写
w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失,若文件不存在则建立该文件
w+ 打开可读写文件,若文件存在则文件长度清为0,即该文件内容会消失,若文件不存在则建立该文件
a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留(EOF符保留)
a+ 以附加的方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留(EOF符保留)
5、fopen
FILE *p=fopen("D:\temp\aaaa.txt","r");//如果文件打开,fopen返回打开的文件的指针,如果失败返回NULL //FILE *p=fopen("D:\temp\aaaa.txt","a"); 用追加的方式打开文件,如果文件不存在,就创建这个文件,如果文件存在,就在文件结尾追加 if(p==NULL){ printf("open fail "); }else{ printf("open success "); } printf("end ");
int main(){ FILE *p=fopen("D:\temp\aaaa.txt","w"); if(p==NULL){ printf("file open fail "); }else{ fputs("hello ",p); fputs("world ",p); fclose(p); } printf("end "); return 0; } 这个程序执行完成之后以16进制方式打开文件,看到 68 65 6C 6C 6F 0D 0A 77 6F 72 6C 64 0D 0A 分别对应 h e l l o w o r l d
int main(){ FILE *p=fopen("D:\temp\aaaa.txt","wb");//如果这里加了b 则按照二进制的方式来读取文件,反之按照文本文件方式来读文件,在Windows系统中,文本模式下,文件以 代表换行,若以文本模式打开文件,并用fputs等函数写入换行符" "时,函数会自动在" "前面加上" " 即实际写入文件的是" ",而如果按照二进制方式读文件,只会读取到 ,不会读取到 //在类Unix/Linux系统中文本模式下,文件以" "代表换行,所以Linux系统中在文本模式和二进制模式下并无区别,在Unix/Linux下w和wb是一样的 if(p==NULL){ printf("file open fail "); }else{ fputs("hello ",p); fputs("world ",p); fclose(p); } printf("end "); return 0; } 这个程序执行完成之后以16进制方式打开文件,看到 68 65 6C 6C 6F 0A 77 6F 72 6C 64 0A 分别对应 h e l l o w o r l d
6、getc putc
int main(){ FILE *p=fopen("D:\text\a.txt","r"); if(p==NULL){ printf("error "); }else{ char c=0; //while(c!=EOF){ // c=getc(p); // printf("%c ",c); //} //上面while的简化写法如下 while((c=getc(p)) != EOF){ printf("%c",c); } fclose(p); } printf("Hello world! "); return 0; }
int main(){//写一个字符 FILE *p=fopen("D:\text\a.txt","w"); if(p==NULL){ printf("error "); }else{ char c=0; putc('a',p); fclose(p); } printf("Hello world! "); return 0; }
7、EOF和feof
通过fgets读文件的时候通常用feof(p)判断是否到了结尾
通过getc读文件的时候通常用(c=getc(p)) != EOF判断是否到了结尾
8、文本文件排序
#include<stdio.h> #include<stdlib.h> #include<string.h> void swap(int *a,int *b){ int tmp=*a; *a=*b; *b=tmp; } void pupple(int *p,int n){ int i; int j; for(i=0;i<n;i++){ for(j=1;j<n-i;j++){ if(p[j-1]>p[j]){ swap(&p[j-1],&p[j]); } } } } int main(void){ int index; int array[10]={0}; char buf[100]; FILE *p=fopen("D:\tmp\a.txt",r); if(p==NULL){ printf("error "); }else{ while(!feof(p)){ memset(buf,0,sizeof(buf));//每次读取文件一行之前都把这个buffer清空 fgets(buf,sizeof(buf),p);//从文件中读一行 index++; array[index]=atoi(buf); fclose(p); } } pupple(array,index); p=fopen("D:\tmp\a.txt","w");//用写的方式打开b.txt int i; for(i=0;i<index;i++){ memset(buf,0,sizeof(buf));//操作buf之前先将它清空 sprintf(buf,"%d ",array[i]);//将数组的成员转化为字符串 fputs(buf,p); } fclose(); return 0; }
动态数组解决上面的问题
int main(){ int index=0; char buf[100]; FILE *p=fopen("D:\tmp\a.txt","r"); while(!feof(p)){ memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf),p); index++; } fclose(p); int *array=calloc(sizeof(int),index); p=fopen("D:\tmp\a.txt","r"); index=0; while(!feof(p)){ memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf),p); array[index]=atoi(buf); index++; } fclose(p); pupple(array,index); p=fopen("D:\tmp\b.txt","w"); int i; for(i=0;i<index;i++){ memset(buf,0,sizeof(buf)); sprintf(buf,"%d ",array[i]); fputs(buf,p); } fclose(); return 0; }
9、解析文件中的加减乘除
#include<stdio.h> #include<string.h> int calc_str(const char *s){ char buf1[100]={0}; char oper; char buf2[100]={0}; int len=strlen(s); int i; for(i=0;i<len;i++){ if(s[i]=='+' || s[i]=='-' || s[i]=='*' || s[i]=='/'){ strncpy(buf1,s,i); oper1=s[i]; break; } } int start=i+1; for(;i<len;i++){ if(s[i]=='='){ strncpy(buf2,&s[start],i-start); } } //printf("buf1=%s,oper1=%c,buf2=%s ",buf1,oper1,buf2); switch(oper1){ case '+': return atoi(buf1)+atoi(buf2); case '-': return atoi(buf1)-atoi(buf2); case '*': return atoi(buf1)*atoi(buf2); case '/': int a=atoi(buf2); if(a){ return atoi(buf1)/atoi(buf2); }else{ return 0; } } } void curReturn(char *s){ int len=strlen(s); if(s[len-1]==' '){ s[len-1]=0; } } int main(){ FILE *p=fopen("D:\tmp\a.txt","r"); FILE *p1=fopen("D:\tmp\b.txt","w"); char buf[1024]; char buf1[1024]; while(!feof(p)){ memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf),p);//从文件中读取一行记录,字符串最后是以' '结尾的 cutReturn(buf); int value=calc_str(buf); memset(buf1,0,sizeof(buf1)); sprintf(buf1,"%s%d ",buf,value); printf("buf1=%s",buf1); fputs(buf1,p1); } fclose(p); fclose(p1); return 0; }
10、fscanf
int main(){ FILE *p=fopen("D:\temp\a.txt","r"); while(!feof(p)){ char buf[100]={0}; //fgets(buf,sizeof(buf),p); fscanf(p,"%s",buf);//fscanf与scanf用法基本一致,fscanf是从一个文件读取输入,scanf是从键盘读取输入 printf("%s",buf); } fclose(p); return 0; } int main(){ FILE *p=fopen("D:\temp\a.txt","r"); while(!feof(p)){ char buf[100]={0}; int a=0; int b=0; fscanf(p,"%d + %d =",&a,&b);//文件中内容必须是固定格式为xx + xx =的形式 printf("%d %d",a,b); } }
11、printf
int main(){ FILE *p=fopen("D:\temp\a.txt","r"); char buf[100]="hello world"; fprintf(p,"%s",buf);//和printf类似,printf输出到屏幕上,fpritnf输出到文件里面 int a=6; int b=7; fclose(p); return 0; }
12、fread
int main(){ FILE *p=fopen("D:\tmp\a.txt","rb");//rb代表用读二进制的方式打开一个文件 char buf[1024]={0}; fread(buf,sizeof(char),1,p)//第一个参数是缓冲区(存放读取的内容),第二个参数是读取的基本单元的大小 //第三个参数是一次读取几个基本单元,第四个参数是打开的文件指针 printf("buf=%s ",buf); fclose(p); return 0; }
int main(){ FILE *p=fopen("D:\tmp\a.txt","rb"); while(!feof(p)){ char buf[10]={0}; fread(buf,sizeof(char),sizeof(buf),p) printf("buf=%s ",buf);//由于文件中每行都是以 结尾的,一个字节一个字节往出读的话就会把 也读到屏幕上,就会显示出非法的字符 } fclose(p); return 0; }
int main(){ FILE *p=fopen("D:\tmp\a.txt","rb"); while(!feof(p)){ char buf[10]={0}; fread(buf,sizeof(char),sizeof(buf)-1,p)//第三个参数设置为buf的长度减1是为了保证buf是一个合法的字符串(有结尾符),在下面的printf中就可以直接将读取到的字符串输出了,而且输出的过程中会根据buf最后一个0自动换行 printf("%s",buf); } fclose(p); return 0; }
int main(){ FILE *p=fopen("D:\tmp\a.txt");; char buf[1024]={0}; //fread返回值代表读取了多少记录数 size_t rec=fread(buf,sizeof(char),sizeof(buf),p);//size_t是无符号整型 printf("%u",res);//如果文件中有3个字符,返回3,有4个字符,返回4,返回的是sizeof(int)的个数 fclose(p); }
int main(){ //假设a.txt中的内容是 //ab //cd //以rb 即二进制方式读文件a.txt时,输出的是61 62 a d 63 64,其中a是 ,d是 //以r 即文本文件方式读文件a.txt时,输出的是61 62 a 63 64 //Windows下如果读取二进制文件必须要加上b,不能只写r FILE *p=fopen("D:\tmp\a.txt","rb"); while(!feof(p)){ char buf[1024]={0}; int res=fread(buf,sizeof(char),sizeof(buf),p); int i; for(i=0;i<res;i++){ printf("%x ",buf[i]); } } fclose(p); return 0; }
13、fwrite
int main(){ FILE *p=fopen("D:\tmp\a.dat","wb"); char buf[1024]={0}; buf[0]='a'; buf[1]='b'; fwrite(buf,sizeof(char),2,p); fclose(p); }
14、二进制文件拷贝
#include<stdlib.h> #include<string.h> int main(){ FILE *p=fopen("D:\tmp\a.wmv","rb"); FILE *p1=fopen("D:\tmp\b.wmv","wb"); char buf[1024 * 4];//每次读4K while(!feof(p)){ memset(buf,0,sizeof(buf)); size_t res = fread(buf,sizeof(char),sizeof(buf),p);//返回从源文件中读取的字节数 fwrite(buf,sizeof(char),res,p1);//从源文件中读取多少字节,就往目标文件写多少字节 //这里一定不能写成fwrite(buf,sizeof(char),sizeof(buf),p1);因为sizeof(buf)是大于等于res的,很有可能拷贝进去多余的字符,如果是拷贝二进制文件,很有可能导致二进制文件打不开 } fclose(p); fclose(p1); return 0; }
15、二进制文件的加密
#include<stdlib.h> #include<string.h> void code(char *p,size_t n){ size_t i; for(i=0;i<n;i++){ p[i]+=3; } } void decode(char *p,size_t n){ size_t i; for(i=0;i<n;i++){ p[i]-=3; } } int main(){ FILE *p=fopen("D:\tmp\a.wmv","rb"); FILE *p1=fopen("D:\tmp\b.wmv","wb"); char buf[1024 * 4];//每次读4K while(!feof(p)){ memset(buf,0,sizeof(buf)); size_t res = fread(buf,sizeof(char),sizeof(buf),p); code(buf,res); fwrite(buf,sizeof(char),res,p1); } fclose(p); fclose(p1); return 0; }
16、stat函数
用stat读取文件比上面的方式效率要高很多
#include<stdlib.h> #include<string.h> #include<sys/stat.h> int main(){ clock_t c1=clock();//时间戳 struct stat st={0}; stat("D:\tmp\a.txt",&st);//调用完stat函数之后,文件相关的信息就保存在stat中了 //printf("%u ",st.st_size);得到文件大小 char *arr=malloc(st.st_size);//根据文件大小在堆中动态分配内存 FILE *p=fopen("D:\tmp\a.txt","rb"); fread(arr,sizeof(char),st.st_size,p);//一下把整个文件放入内存 fclose(p); p=fopen("D:\tmp\b.wmv","wb"); fwrite(array,sizeof(char),st.st_size,p);//将堆中的信息一下都写入文件 fclose(p); clock_t c2=clock();//时间戳 printf("%u",c2-c1); return 0; }
17、结构体与二进制文件
struct student{ char a; int age; }; int main(){ struct student st={'a',25}; FILE *p=fopen("D:\tmp\a.dat","wb");//a.dat里面内容是61 00 00 00 1E 00 00 00 fwrite(&st,sizeof(st),1,p); fclose(p); }
18、读取大文件
#include<time.h> int main(){ srand(time(NULL)); int i; FILE *p=fopen("D:\tmp\a.txt","w"); for(i=0;i<1000000000;i++){ fprintf(p,"%d ",rand() % 256); } fclose(p); printf("end"); return 0; } //生成的a.txt会很大,大到打开a.txt时都加载不出来,几十兆就打不开了 //如果我们需要对a.txt中的数字进行排序,如果不操作堆内存的话要怎么做呢? //先考虑小文件的情况 int main(){ FILE *p=fopen("D:\tmp\a.txt","r"); int array[256]={0}; while(!feof(p)){ char buf[100]={0}; fgets(buf,sizeof(buf),p);//得到一行 if(buf[0]!=0){//有时候我们会发现b.txt里面第一行是0,但是a.txt文件里面没有哪一行有0,那么证明a.txt文件里面的最后一行是空行 int value=atoi(buf);//将得到的行转化为整数 array[value]++; } } fclose(p); p=fopen("D:\temp\b.txt","w"); int i; int j; for(i=0;i<513;i++){ for(j=0;j<array[i];j++){ fprintf(p,"%d ",i); } } fclose(p); printf("end"); return 0; }
19、fseek
struct student{ char name[10]; int age; }; int main01(){ struct student st[10]={0}; int i; for(i=0;i<10;i++){ scanf("%s",st[i].name); scanf("%d",&st[i].age); } FILE *p=fopen("D:\txt\a.dat","wb"); fwrite(st,sizeof(struct student),10,p); return 0; } int main(){ struct student st={0}; FILE *p=fopen("D:\txt\a.dat","rb"); //读取第一个结构体 memset(&st,0,sizeof(struct student)); fread(&st,sizeof(struct student),1,p); printf("name=%s,age=%d ",st.name,st.age); //读取第二个结构体 memset(&st,0,sizeof(struct student)); fread(&st,sizeof(struct student),1,p); printf("name=%s,age=%d ",st.name,st.age); //读取第三个结构体 memset(&st,0,sizeof(struct student)); fread(&st,sizeof(struct student),1,p); printf("name=%s,age=%d ",st.name,st.age); //目前文件指针p在第4个结构,如果在这时想回去的话,可以通过fseek实现 //或者希望从中间开始读文件,或者倒着往回读,都可以用fseek实现 fseek(p,sizeof(struct student),SEEK_SET);//SEEK_SET是一个宏,代表文件的开始位置,第二个参数意思是在第三个参数的基础上向后偏移sizeof(struct student)个字节读取 //第二个参数可以是负值 //除了SEEK_SET之外,还有SEEK_CUR(当前位置),SEEK_END(文件结尾位置) }