• C语言4——文件操作


    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(文件结尾位置)
    }
  • 相关阅读:
    备份
    >> 与 > >
    为什么需要htons(), ntohl(), ntohs(),htons() 函数
    小技巧
    C++头文件
    宏定义中的#,##操作符和... and _ _VA_ARGS_ _与自定义调试信息的输出
    OpenCV摄像头简单程序
    [转]让Linux的tty界面支持中文
    opencv 2 computer vision application programming第四章翻译
    OpenCV条码(6)简单实现
  • 原文地址:https://www.cnblogs.com/zhaohuiziwo901/p/5093170.html
Copyright © 2020-2023  润新知