zoukankan      html  css  js  c++  java
  • C语言 文件操作

    C语言 文件操作

    文件概述

    一、磁盘文件和设备文件

    1、磁盘文件

    指一组相关数据的有序集合,通常存储在外部介质(如磁盘)上,使用时才调入内存。

    2、设备文件

    在操作系统中把每一个与主机相连的输入、输出设备看作是一个文件,把它们的输入、输出等同于对磁盘文件的读和写。

    二、磁盘文件的分类

    计算机的存储在物理上是二进制的,所以物理上所有的磁盘文件本质上都是一样的:以字节为单位进行顺序存储。

     从用户或者操作系统使用的角度(逻辑上)把文件分为:

    • 文本文件:基于字符编码的文件
    • 二进制文件:基于值编码的文件

    三、文本文件和二进制文件

    1、文本文件

    • 基于字符编码,常见编码有ASCII、UNICODE等
    • 一般可以使用文本编辑器直接打开

    数5678的以ASCII存储形式(ASCII码)为:

    00110101 00110110 00110111 00111000

    2、二进制文件

    • 基于值编码,自己根据具体应用,指定某个值是什么意思
    • 把内存中的数据按其在内存中的存储形式原样输出到磁盘上

     数5678的存储形式(二进制码)为:

    00010110 00101110

    文件打开和关闭

    一、文件指针

    在C语言中用一个指针变量指向一个文件,这个指针称为文件指针

    typedef struct
    {
           short           level;       //缓冲区"满"或者"空"的程度
           unsigned        flags;       //文件状态标志
           char            fd;          //文件描述符
           unsigned char   hold;        //如无缓冲区不读取字符
           short           bsize;       //缓冲区的大小
           unsigned char   *buffer;     //数据缓冲区的位置
           unsigned        ar;          //指针,当前的指向
           unsigned        istemp;      //临时文件,指示器
           short           token;       //用于有效性的检查
    }FILE;

      FILE是系统使用typedef定义出来的有关文件信息的一种结构体类型,结构中含有文件名、文件状态和文件当前位置等信息。

      声明FILE结构体类型的信息包含在头文件“stdio.h”中,一般设置一个指向FILE类型变量的指针变量,然后通过它来引用这些FILE类型变量。通过文件指针就可对它所指的文件进行各种操作。

    C语言中有三个特殊的文件指针由系统默认打开,用户无需定义即可直接使用:

    • stdin: 标准输入,默认为当前终端(键盘),我们使用的scanf、getchar函数默认从此终端获得数据。
    • stdout:标准输出,默认为当前终端(屏幕),我们使用的printf、puts函数默认输出信息到此终端。
    • stderr:标准出错,默认为当前终端(屏幕),我们使用的perror函数默认输出信息到此终端。

    二、文件打开

    1、说明

    任何文件使用之前必须打开:

    #include <stdio.h>
    FILE * fopen(const char * filename, const char * mode);

    功能:打开文件
    参数:

    • filename:需要打开的文件名,根据需要加上路径
    • mode:打开文件的模式设置

    返回值:

    • 成功:文件指针
    • 失败:NULL

    2、第一个参数的几种形式

    FILE *fp_passwd = NULL;
     
    //相对路径:
    //打开当前目录passdw文件:源文件(源程序)所在目录
    FILE *fp_passwd = fopen("passwd.txt", "r");
          
    //打开当前目录(test)下passwd.txt文件
    fp_passwd = fopen(". / test / passwd.txt", "r");
          
    //打开当前目录上一级目录(相对当前目录)passwd.txt文件
    fp_passwd = fopen(".. / passwd.txt", "r");
                 
    //绝对路径:
    //打开C盘test目录下一个叫passwd.txt文件
    fp_passwd = fopen("c://test//passwd.txt","r");

    3、第二个参数的几种形式(打开文件的方式)

    注意事项:

    • b是二进制模式的意思,b只是在Windows有效,在Linux用r和rb的结果是一样的
    • Unix和Linux下所有的文本文件行都是 结尾,而Windows所有的文本文件行都是 结尾
    • 在Windows平台下,以“文本”方式打开文件,不加b:
    • 当读取文件的时候,系统会将所有的 " " 转换成 " "
    • 当写入文件的时候,系统会将 " " 转换成 " " 写入
    • 以"二进制"方式打开文件,则读写都不会进行这样的转换
    • 在Unix/Linux平台下,“文本”与“二进制”模式没有区别," " 作为两个字符原样输入输出

    打开模式

    含义

    r或rb

    以只读方式打开一个文本文件(不创建文件,若文件不存在则报错)

    w或wb

    以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)

    a或ab

    以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件

    r+或rb+

    以可读、可写的方式打开文件(不创建新文件)

    r+或rb+

    以可读、可写的方式打开文件(不创建新文件)

    w+或wb+

    以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)

    a+或ab+

    以添加方式打开文件,打开文件并在末尾更改文件,若文件不存在则创建文件

    4、案例

    #include <stdio.h>
    
    int main(void)
    {
           FILE *fp = NULL;
     
           // "\"这样的路径形式,只能在windows使用
           // "/"这样的路径形式,windows和linux平台下都可用,建议使用这种
           // 路径可以是相对路径,也可是绝对路径
           fp = fopen("../test", "w");
           //fp = fopen("..\test", "w");
     
           if (fp == NULL) //返回空,说明打开失败
           {
                  //perror()是标准出错打印函数,能打印调用库函数出错原因
                  perror("open");
                  return -1;
           }
     
           return 0;
    }
    文件打开 使用案例

    三、文件关闭

    1、说明

    任何文件在使用后应该关闭:

    • 打开的文件会占用内存资源,如果总是打开不关闭,会消耗很多内存
    • 一个进程同时打开的文件数是有限制的,超过最大同时打开文件数,再次调用fopen打开文件会失败
    • 如果没有明确的调用fclose关闭打开的文件,那么程序在退出的时候,操作系统会统一关闭。
    #include <stdio.h>
    int fclose(FILE * stream);

    功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。
    参数:

    • stream:文件指针

    返回值:

    • 成功:0
    • 失败:-1

    2、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 定义文件指针
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
        
        // 判断文件是否打开成功
        // 1、找不到文件
        // 2、文件权限(读、写、执行)
        // 3、程序打开文件超出上限 65535
        if (fp == NULL)
        {
            printf("打开文件失败
    ");
            return -1;
        }
        
        printf("文件打开成功:%p
    ",fp);
        
        // 关闭文件指针
        fclose(fp);
    
        return 0;
    }
    文件关闭 使用案例

    文件字符读写

    一、写文件

    1、说明

    #include <stdio.h>
    int fputc(int ch, FILE * stream);

    功能:将ch转换为unsigned char后写入stream指定的文件中
    参数:

    • ch:需要写入文件的字符
    • stream:文件指针

    返回值:

    • 成功:成功写入文件的字符
    • 失败:返回-1

    2、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 以写的方式打开文件、如果文件不存在则创建一个新文件、如果文件存在则清空内容
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w");
        
        if (!fp)
        {
            printf("打开文件失败
    ");
            return -1;
        }
        
        // 创建字符
        // char ch = 'a';
    
        // 字符写入
        // 约束:if(value==-1)
        // fputc(ch, fp);
        
        // 通过键盘输入方式存字符
        char ch;
        while (1)
        {
            scanf("%c", &ch);
            // 输入@关闭文件
            if (ch == '@')
            {
                break;
            }
            fputc(ch, fp);
        }
    
    
        // 关闭文件
        fclose(fp);
    
        return 0;
    }
    fputc 使用案例

    二、文件结尾

    1、概述

      在C语言中,EOF表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放。我们知道,ASCII代码值的范围是0~127,不可能出现-1,因此可以用EOF作为文件结束标志。

    #define EOF     (-1)

      当把数据以二进制形式存放到文件中时,就会有-1值的出现,因此不能采用EOF作为二进制文件的结束标志。为解决这一个问题,ANSI C提供一个feof函数,用来判断文件是否结束。feof函数既可用以判断二进制文件又可用以判断文本文件。

    2、说明

    #include <stdio.h>
    int feof(FILE * stream);

    功能:检测是否读取到了文件结尾。判断的是最后一次“读操作的内容”,不是当前位置内容(上一个内容)。
    参数:

    • stream:文件指针

    返回值:

    • 非0值:已经到文件结尾
    • 0:没有到文件结尾

    3、案例

    三、读文件

    1、说明

    #include <stdio.h>
    int fgetc(FILE * stream);

    功能:从stream指定的文件中读取一个字符
    参数:

    • stream:文件指针

    返回值:

    • 成功:返回读取到的字符
    • 失败:-1

    2、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
        
        if (!fp)
        {
            printf("打开文件失败
    ");
            return -1;
        }
        
        // 定义字符
        char ch;
    
        // 文件字符读取
        // 文件默认结尾为 -1
        // ch = fgetc(fp);
    
        // 不能修改文件指针
        // 文件在读取时光标流会自动向下移动
        // fp++;
    
        // 循环打印
        while ((ch = fgetc(fp)) != EOF)
        {
            printf("%c", ch);
        }
    
        // 关闭文件
        fclose(fp);
    
        return 0;
    }
    fgetc 使用案例

    四、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        FILE* fp1 = fopen("C:/Users/Administrator/Desktop/解密.txt", "r");
        FILE* fp2 = fopen("C:/Users/Administrator/Desktop/加密.txt", "w");
     if (!fp1 || !fp2)return -1;
        char ch;
        while ((ch = fgetc(fp1)) != EOF)
        {
            // 加密
            ch++;
            fputc(ch, fp2);
        }
    
        fclose(fp1);
        fclose(fp2);
    
        return 0;
    }
    字符读写 使用案例:加密
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        FILE* fp1 = fopen("C:/Users/Administrator/Desktop/加密.txt", "r");
        FILE* fp2 = fopen("C:/Users/Administrator/Desktop/解密文件.txt", "w");
        if (!fp1 || !fp2)return -1;
        char ch;
        while ((ch = fgetc(fp1)) != EOF)
        {
            // 解密
            ch--;
            fputc(ch, fp2);
        }
    
        fclose(fp1);
        fclose(fp2);
    
        return 0;
    }
    字符读写 使用案例:解密

    文件行读写

    一、写文件

    1、说明

    #include <stdio.h>
    int fputs(const char * str, FILE * stream);

    功能:将str所指定的字符串写入到stream指定的文件中,字符串结束符 '' 不写入文件。
    参数:

    • str:字符串
    • stream:文件指针

    返回值:

    • 成功:0
    • 失败:-1

    2、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 打开文件
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w");
        // 判断
        if (!fp)return -1;
    
        // 创建字符串
        // "你想怎么滴吧" 遇到则停止
        // char ch[] = "你想怎么滴吧";
        //fputs(ch, fp);
    
        // 通过键盘输入获取字符串
        char* p = (char*)malloc(sizeof(char) * 1024);
        while (1)
        {
            memset(p, 0, 1024);
            
            // 问题:scanf("%s", p);无法接收回车空格
            // 方式一、fgets() 可接收空格
            // 方式二、scanf("%[^
    ]", p); 避免吞噬空格回车
            scanf("%[^
    ]", p);
            // 吞噬回车
    
            getchar();
    
            // 停止输入命令:comm=exit
            if (!strcmp(p, "comm=exit",9))break;
    
            // 追加换行符
            strcat(p, "
    ");
    
            // 写入字符串
            fputs(p, fp);
        }
    
        free(p);
        fclose(fp);
    
        return 0;
    }
    fputs 使用案例

    二、读文件

    1、说明

    #include <stdio.h>
    char * fgets(char * str, int size, FILE * stream);

    功能:从stream指定的文件内读入字符,保存到str所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,最后会自动加上字符 '' 作为字符串结束。
    参数:

    • str:字符串
    • size:指定最大读取字符串的长度(size - 1)
    • stream:文件指针

    返回值:

    • 成功:成功读取的字符串
    • 读到文件尾或出错: NULL

    2、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 打开文件
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
        // 判断
        if (!fp)return -1;
    
        // 开辟堆空间
        char* p = (char*)malloc(sizeof(char) * 1024);
        
        // 初始化内存空间 
        // memset(p, 0, 5);
        // 通过堆开放内存,打印文件中100个字节
        // 根据光标位置继续向下读取字符串
        // fgets(p, 5, fp);
        // printf("%s", p);
        
        // 打印
        // feof(文件指针):判断文件是否到结尾 可以判断文本文件也可以判断二进制文件
        // 如果到文件结尾返回值为 非0的值
        // 如果没到文件结尾返回值为 0的值
        while (!feof(fp))
        {
            memset(p, 0, 100);
            fgets(p, 100, fp);
            printf("%s", p);
        }
    
        free(p);
        fclose(fp);
    
        return 0;
    }
    fgets 使用案例

    三、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    enum opt
    {
        add,sub,mlt,dive
    };
    
    int main(void)
    {
        
        srand((size_t)time(NULL));
        
        // 打开文件
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w");
        // 判断
        if (!fp)return -1;
    
        int a, b;
        char c; // + - * /
        char * p = (char*)malloc(sizeof(char) * 20);
    
        for (int i = 0; i < 100; i++)
        {
            a = rand() % 10 + 1;
            b = rand() % 10 + 1;
    
            switch (rand() % 4)
            {
            case add:c = '+';break;
            case sub:c = '-';break;
            case mlt:c = '*';break;
            case dive:c = '/';break;
            }
    
            memset(p, 0,20);
            sprintf(p, "%d%c%d=
    ", a, c, b);
            fputs(p, fp);//fgets(p,size,fp)
    
        }
    
        free(p);
        fclose(fp);
        p = NULL;
        fp = NULL;
    
        return 0;
    }
    文件行读写 使用案例:四则运算(打印运算表达式)
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        
        srand((size_t)time(NULL));
        
        // 打开文件
        FILE* fp1 = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
        FILE* fp2 = fopen("C:/Users/Administrator/Desktop/xsk2.txt", "w");
        // 判断
        if (!fp1 || !fp2)return -1;
    
        // 判断文件结尾
        // !feof(fp);
        // EOF -1
    
        int a, b, sum;
        char c;
        char * p = (char*)malloc(sizeof(char) * 20);
    
        for (int i = 0; i < 100; i++)
        {
            memset(p, 0, 20);
            // 打印1行内容
            fgets(p, 20, fp1);
    
            sscanf(p, "%d%c%d=
    ", &a, &c, &b);
    
            switch (c)
            {
            case '+':sum = a + b; break;
            case '-':sum = a - b; break;
            case '*':sum = a * b; break;
            case '/':sum = a / b; break;
            }
    
            memset(p, 0, 20);
            sprintf(p, "%d%c%d=%d
    ", a, c, b, sum);
            fputs(p, fp2);
        }
    
        free(p);
        fclose(fp1);
        fclose(fp2);
    
        return 0;
    }
    文件行读写 使用案例:四则运算(打印运算表达式结果)

    文件格式化

    一、写文件

    1、说明

    #include <stdio.h>
    int fprintf(FILE * stream, const char * format, ...);

    功能:根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符 '' 为止。
    参数:

    • stream:已经打开的文件
    • format:字符串格式,用法和printf()一样

    返回值:

    • 成功:实际写入文件的字符个数
    • 失败:-1

    2、案例

    二、读文件

    1、说明

    #include <stdio.h>
    int fscanf(FILE * stream, const char * format, ...);

    功能:从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。
    参数:

    • stream:已经打开的文件
    • format:字符串格式,用法和scanf()一样

    返回值:

    • 成功:参数数目,成功转换的值的个数
    • 失败: - 1

    2、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        
        // 打开文件
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
        // 判断
        if (!fp)return -1;
    
        char * p = (char*)malloc(sizeof(char) * 100);
        
        // 直接格式化取出字符串
        // 遇到空格与回车就结束
        // fscanf(fp, "%s", p);
        // printf("%s", p);
    
    
        int a, b, c;
    
        // 1+2=3
        // 处理表达式
        fscanf(fp, "%d+%d=%d", &a,&b,&c);
    
        printf("%d
    ", a);
        printf("%d
    ", b);
        printf("%d
    ", c);
    
        free(p);
        fclose(fp);
    
        return 0;
    }
    fscanf 使用案例

    三、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        srand((size_t)time(NULL));
        // 打开文件
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk1.txt", "w");
        // 判断
        if (!fp)return -1;
    
        int a, b;
        char c;
    
        for (int i = 0; i < 100; i++)
        {
            a = rand() % 10 + 1;
            b = rand() % 10 + 1;
    
            switch (rand() % 4)
            {
            case 0:c = '+'; break;
            case 1:c = '-'; break;
            case 2:c = '*'; break;
            case 3:c = '/'; break;
            }
            fprintf(fp, "%d%c%d=
    ", a, c, b);
        }
    
        fclose(fp);
    
        return 0;
    }
    文件格式化 使用案例:四则运算案例(打印运算表达式)
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        srand((size_t)time(NULL));
        // 打开文件
        FILE* fp1 = fopen("C:/Users/Administrator/Desktop/xsk1.txt", "r");
        FILE* fp2 = fopen("C:/Users/Administrator/Desktop/xsk2.txt", "w");
        // 判断
        if (!fp1||!fp2)return -1;
    
        int a, b, sum;
        char c;
    
        for (int i = 0; i < 100; i++)
        {
            fscanf(fp1, "%d%c%d
    ", &a, &c, &b);
    
            switch (c)
            {
            case '+':sum = a + b; break;
            case '-':sum = a - b; break;
            case '*':sum = a * b; break;
            case '/':sum = a / b; break;
            }
            fprintf(fp2, "%d%c%d=%d
    ", a, c, b,sum);
        }
    
        fclose(fp1);
        fclose(fp2);
        return 0;
    }
    文件格式化 使用案例:四则运算案例(打印运算表达式结果)
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 大文件排序 打印1000数字
        srand((size_t)time(NULL));
        // 打开文件
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w");
        // 判断
        if (!fp)return -1;
    
    
        for (int i = 0; i < 1000; i++)
        {
            fprintf(fp, "%d
    ", rand() % 256);
        }
        fclose(fp);
        return 0;
    }
    文件格式化 使用案例:大文件排序(打印1000行数字)
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 打开文件
        FILE* fp1 = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
        FILE* fp2 = fopen("C:/Users/Administrator/Desktop/xsk2.txt", "w");
        // 判断
        if (!fp1||!fp2)return -1;
    
        int* arr = (int*)malloc(sizeof(int) * 256);
    
        memset(arr, 0, sizeof(int) * 256);
    
        // 直接插入
        // 数据一定要在一个范围内
        for (int i = 0; i < 1000; i++)
        {
            int value;
            fscanf(fp1, "%d
    ", &value);
            // 数据的个数放在对应的下标
            arr[value]++;
        }
    
        for (int i = 0; i < 256; i++)
        {
            for (int j = 0; j < arr[i]; j++)
            {
                fprintf(fp2, "%d
    ", i);
            }
        }
    
        free(arr);
        fclose(fp1);
        fclose(fp2);
    
        return 0;
    }
    文件格式化 使用案例:大文件排序(直接插入排序)

    文件块读写

    一、写文件

    1、说明

    #include <stdio.h>
    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

    功能:以数据块的方式给文件写入内容
    参数:

    • ptr:准备写入文件数据的地址
    • size: size_t 为 unsigned int类型,此参数指定写入文件内容的块数据大小
    • nmemb:写入文件的块数,写入文件数据总大小为:size * nmemb
    • stream:已经打开的文件指针

    返回值:

    • 成功:实际成功写入文件数据的块数目,此值和nmemb相等
    • 失败:0

    2、案例

    typedef struct Stu
    {
           char name[50];
           int id;
    }Stu;
     
    Stu s[3];
    int i = 0;
    for (i = 0; i < 3; i++)
    {
           sprintf(s[i].name, "stu%d%d%d", i, i, i);
           s[i].id = i + 1;
    }
     
    int ret = fwrite(s, sizeof(Stu), 3, fp);
    printf("ret = %d
    ", ret);
    fwrite 使用案例

    二、读文件

    1、说明

    #include <stdio.h>
    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

    功能:以数据块的方式从文件中读取内容
    参数:

    • ptr:存放读取出来数据的内存空间
    • size: size_t 为 unsigned int类型,此参数指定读取文件内容的块数据大小
    • nmemb:读取文件的块数,读取文件数据总大小为:size * nmemb
    • stream:已经打开的文件指针

    返回值:

    • 成功:实际成功读取到内容的块数,如果此值比nmemb小,但大于0,说明读到文件的结尾。
    • 失败:0

    2、案例

    typedef struct Stu
    {
           char name[50];
           int id;
    }Stu;
     
    Stu s[3];
    int ret = fread(s, sizeof(Stu), 3, fp);
    printf("ret = %d
    ", ret);
     
    int i = 0;
    for (i = 0; i < 3; i++)
    {
           printf("s = %s, %d
    ", s[i].name, s[i].id);
    }
    fread 使用案例

    三、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 写入数据
        // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "wb");
        // 判断
        // if (!fp)return -1;
        // int a = 5678;
        // 以二级制格式写入
        // fwrite(&a, sizeof(int), 1, fp);
        // fclose(fp);
        
        // 数组写入
        // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "wb");
        // 判断
        // if (!fp)return -1;
        // int arr[] = { 1,2,3,4,5,6,7,8,10 };
        // fwrite(arr, sizeof(int), 10, fp);
        // fclose(fp);
    
        // 读取数据
        // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "rb");
        // 判断
        // if (!fp)return -1;
        // int value;
        // fread(&value, sizeof(int), 1, fp);
        // printf("%d
    ", value);
        // fclose(fp);
    
        // 数组读取
        // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "rb");
        // 判断
        // if (!fp)return -1;
        // int arr[10] = { 0 };
        // fread(arr, sizeof(int), 10, fp);
        // for (int i = 0; i < 10; i++)
        // {
        //     printf("%d
    ", arr[i]);
        // }
    
        return 0;
    }
    文件块读写 使用案例

    文件随机读写

    一、说明

    #include <stdio.h>
    int fseek(FILE *stream, long offset, int whence);

    功能:移动文件流(文件光标)的读写位置。
    参数:

    • stream:已经打开的文件指针
    • offset:根据whence来移动的位移数(偏移量),可以是正数,也可以负数,如果正数,则相对于whence往右移动,如果是负数,则相对于whence往左移动。如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸。
    • whence:其取值如下:
    • SEEK_SET:从文件开头移动offset个字节
    • SEEK_CUR:从当前位置移动offset个字节
    • SEEK_END:从文件末尾移动offset个字节

    返回值:

    • 成功:0
    • 失败:-1

    二、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r");
    
        if (!fp)
        {
            return -1;
        }
    
        char arr[100];
    
        // 输出第一行
        memset(arr, 0, 100);
        fgets(arr, 100, fp);
        printf("%s", arr);
    
        // 输出第二行
        memset(arr, 0, 100);
        fgets(arr, 100, fp);
        printf("%s", arr);
    
        // 光标偏移
        // 文件随机读写
        // 从当前位置偏移,往回偏移8个
        fseek(fp, -8, SEEK_CUR);
    
        // 输出从光标位置输出
        memset(arr, 0, 100);
        fgets(arr, 100, fp);
        printf("%s", arr);
    
        fclose(fp);
        return 0;
    }
    文件随机读写 使用案例
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r+");
    
        if (!fp)
        {
            return -1;
        }
    
        // 从文件末尾追加
        fseek(fp,-1, SEEK_END);
    
        fputs("aaaa",fp);
    
        fclose(fp);
        return 0;
    }
    文件随机读写 使用案例:2

    文件流

    一、文件流获取

    1、说明

    #include <stdio.h>
    long ftell(FILE *stream);

    功能:获取文件流(文件光标)的读写位置。
    参数:

    • stream:已经打开的文件指针

    返回值:

    • 成功:当前文件流(文件光标)的读写位置
    • 失败:-1

    2、案例

    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "a");
    
        if (!fp)
        {
            return -1;
        }
    
        // 查看当前位置
        long pos = ftell(fp);
    
        printf("%ld
    ", pos);
    
        fclose(fp);
        return 0;
    } 
    ftell 使用案例

    二、文件流修改

    1、说明

    #include <stdio.h>
    void rewind(FILE *stream);

    功能:把文件流(文件光标)的读写位置移动到文件开头。
    参数:

    • stream:已经打开的文件指针

    返回值:
    无返回值

    2、案例

    typedef struct Stu
    {
           char name[50];
           int id;
    }Stu;
     
    //假如已经往文件写入3个结构体
    //fwrite(s, sizeof(Stu), 3, fp);
     
    Stu s[3];
    Stu tmp;
    int ret = 0;
     
    //文件光标读写位置从开头往右移动2个结构体的位置
    fseek(fp, 2 * sizeof(Stu), SEEK_SET);
     
    //读第3个结构体
    ret = fread(&tmp, sizeof(Stu), 1, fp);
    if (ret == 1)
    {
           printf("[tmp]%s, %d
    ", tmp.name, tmp.id);
    }
     
    //把文件光标移动到文件开头
    //fseek(fp, 0, SEEK_SET);
    rewind(fp);
     
    ret = fread(s, sizeof(Stu), 3, fp);
    printf("ret = %d
    ", ret);
     
    int i = 0;
    for (i = 0; i < 3; i++)
    {
           printf("s === %s, %d
    ", s[i].name, s[i].id);
    }
    rewind 使用案例

    文件状态

    一、说明

    #include <sys/types.h>
    #include <sys/stat.h>
    int stat(const char *path, struct stat *buf);

    功能:获取文件状态信息
    参数:

    • path:文件名
    • buf:保存文件信息的结构体

    返回值:

    • 成功:0
    • 失败-1

    二、使用

    struct stat {
           dev_t         st_dev;          //文件的设备编号
           ino_t         st_ino;          //节点
           mode_t        st_mode;         //文件的类型和存取的权限
           nlink_t       st_nlink;        //连到该文件的硬连接数目,刚建立的文件值为1
           uid_t         st_uid;          //用户ID
           gid_t         st_gid;          //组ID
           dev_t         st_rdev;         //(设备类型)若此文件为设备文件,则为其设备编号
           off_t         st_size;         //文件字节数(文件大小)
           unsigned long st_blksize;      //块大小(文件系统的I/O 缓冲区大小)
           unsigned long st_blocks;       //块数
           time_t        st_atime;        //最后一次访问时间
           time_t        st_mtime;        //最后一次修改时间
           time_t        st_ctime;        //最后一次改变时间(指属性)
    };

    三、案例

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <stdio.h>
     
    int main(int argc, char **args)
    {
           if (argc < 2)
                  return 0;
         
    // 文件状态结构体变量
           struct stat st = { 0 };
         
           stat(args[1], &st);
           int size = st.st_size;//得到结构体中的成员变量
           printf("%d
    ", size);
           return 0;
    }
    stat 使用案例
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #define MAX (1024*1024*8)
    
    // 拷贝大文件
    int main(int argc,char* argv[])
    {
        // 显示参数内容
        //for (int i = 0; i < argc; i++)
        //{
        //    printf("%s
    ", argv[i]);
        //}
    
        // 用户输入参数缺少
        if (argc < 3)
        {
            printf("缺少参数
    ");
            return -1;
        }
    
        // C:/copy.exe C:/xsk.txt C:/xsk/xsk.txt
        // argv[0] 程序名称、文件大小是50M
        FILE* fp1 = fopen(argv[1], "rb");
        FILE* fp2 = fopen(argv[2], "wb");
    
        if (!fp1 || !fp2)
        {
            printf("赋值文件出错
    ");
            return -2;
        }
    
        char* temp = NULL;
        int size = 0;
    
        // 求文件大小
        struct stat st;
        stat(argv[1], &st);
    
        // 根据文件实际大小开辟空间
        if (st.st_size > MAX)
        {
            temp = (char*)malloc(sizeof(char) * MAX);
            size = MAX;
        }
        else
        {
            temp = (char*)malloc(sizeof(char) * st.st_size + 10);
            size = st.st_size + 10;
        }
    
        // 接收每次读取的字节数
        int count = 0;
    
        while (!feof(fp1))
        {
            memset(temp, 0, size);
            // count=读取实际字节数、读取内容
            count = fread(temp, sizeof(char), size,fp1);
            // 根据字节大小写入
            fwrite(temp, sizeof(char), count, fp2);
        }
    
        free(temp);
        fclose(fp1);
        fclose(fp2);
        return 0;
    }
    stat 使用案例:大文件拷贝操作

    文件删除

    一、说明

    #include <stdio.h>
    int remove(const char *pathname);

    功能:删除文件
    参数:

    • pathname:文件名

    返回值:

    • 成功:0
    • 失败:-1

    二、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 删除文件
        int value = remove("C:/Users/Administrator/Desktop/xsk.txt");
        if (value == 0)
        {
            printf("删除成功
    ");
        }
        else
        {
            printf("删除失败
    ");
        }
    
        return 0;
    }
    文件删除 使用案例

    文件剪切重命名

    一、说明

    #include <stdio.h>
    int rename(const char *oldpath, const char *newpath);

    功能:把oldpath的文件名改为newpath
    参数:

    • oldpath:旧文件名
    • newpath:新文件名

    返回值:

    • 成功:0
    • 失败: - 1

    二、案例

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main(void)
    {
        // 重命名、移动文件
        int value = rename("C:/Users/Administrator/Desktop/xsk.txt","C:/Users/Administrator/Desktop/xsk_new.txt");
        if (value == 0)
        {
            printf("改名成功
    ");
        }
        else
        {
            printf("改名失败
    ");
        }
        return 0;
    }
    文件剪切重命名 使用案例
  • 相关阅读:
    Python学习笔记六:集合
    Python学习笔记五:字符串常用操作,字典,三级菜单实例
    Python学习笔记四:列表,购物车程序实例
    Python学习笔记三:数据类型
    python学习笔记二:if语句及循环语句,断点,模块,pyc
    Python学习笔记一:第一个Python程序,变量,字符编码与二进制,用户交互程序
    JS教程:从0开始
    基于Token认证的多点登录和WebApi保护
    数据库高级对象(存储过程,事务,锁,游标,触发器)
    Sql基础(零基础学数据库_SqlServer版)
  • 原文地址:https://www.cnblogs.com/xiangsikai/p/12382061.html
Copyright © 2011-2022 走看看