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没有区别。
 
    

 
    在windows下有区别
    

 
    区别就在于,如果你在windows下面,写入的是文本文件,那么会把所有的换行或者说所有的
替换成
,二进制不会替换。
 
     在mac或者Linux或者UNIX下,无论写入文本文件还是二进制文件,
都不会做任何替换。
 
 文件指针就叫 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
",ch);              //a
         
         char ch2 = fgetc(fp);            
         printf("%c
",ch2);              //b
         
         char ch3 = fgetc(fp);
         printf("%c
",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个有效字符,因为还有一个字符帮你加''
                2、如果读取到换行(
),那么会停止读取,然后把换行也读取来,并且在换行后面加
 
 
读取多行:
    文件中的文本行数无法确定,所以需要一个循环(死循环)。
 
    判断读取到末尾:
            feof(文件指针);
                如果返回的是1(真),代表读取到末尾。
                如果返回的是0,代表没有到末尾。
 
*/

#include <stdio.h>

/**
 *  写入一串字符串
 */
void writeString(){
    FILE *fp = fopen("/Users/ios/Desktop/1.txt", "w");
    if(fp != NULL){
        //写字符串
        fputs("我爱家乡妹子多", fp);
        printf("写完了
");
        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个有效的,还有一个位置是帮你加一个''

        printf("%s
",str);
        char str2[100];
        fgets(str2, 100, fp);
        printf("%s
",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("成功了
");
        
        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
",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, "哈哈哈哈哈
"); //跟printf没差别,stdout代表在控制台输出
    
    int num;
    fscanf(stdin, "%d",&num); //stdin在控制台输入
    
    printf("num=%d
",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
",ch,num);//a 99
        
        char str[50] = {0};
        char str2[50];
        fscanf(fp, "%s
%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("做完了!
");
            fclose(fpWrite);
        }
        fclose(fpRead);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/bobo-pcb/p/4942723.html