黑马程序员——c语言基础:文件管理

本文详细介绍了C语言中的文件管理,包括文件的基本概念、类型、操作步骤及原理。通过实例演示了文件的打开、读写、关闭过程,讲解了ASCII码和二进制文件的区别,以及字符、字符串、数据块的读写函数。同时,文章还涵盖了文件操作中的缓冲区、输入输出流、文件指针和文件使用方式,如读写模式(r, w, a等)。此外,还讨论了文件的随机读写、定位和错误检测等功能,帮助读者全面掌握C语言中的文件管理技巧。" 100102241,5621586,Linux系统网络配置:IP与MAC地址修改指南,"['Linux', '网络配置', 'IP', 'MAC', '命令行工具']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.文件的基本概念和文件操作


 文件:文件指存储在外部介质上数据的集合,这个数据集有一个名称,叫做文件名。

 

 文件的分类:

    1)从用户的角度看,文件可分为普通文件和设备文件两种。

    2)从文件的编码方式来看,文件可分为ASCII码文件和二进制文件两种。

        ASCII文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码。

        二进制文件是按二进制的编码方式来存放文件的。

 

 文件操作的步骤

    1)引入头文件(stdio.h

    2)定义文件指针

        FILE *fp = NULL;

    3)打开文件

        fopen(文件名,操作方式); // 如果打开成功,返回文件的首地址,如果打开失败,返回NULL

    4)文件读写

        对文件的读和写是最常用的文件操作。在C语言中提供了多种文件读写的函数:

        字符读写函数:fgetcfputc

        字符串读写函数:fgersfputs

        数据块读写函数:freadfwrite

        格式化读写函数:fscanffprintf

    5)关闭文件

        fclose(文件指针);

 

 文件操作的原理

    1)文件缓冲区:

        ANSIC标准采用缓冲文件系统出来数据文件,所谓缓冲文件系统是指系统自动地在内存区为程序中每一个正在使用的文件开辟一个文件缓冲区。

        从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘区。

        如果从磁盘向计算机读入数据,则一次从磁盘文件将一批数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(给程序变量)。

    2)输入输出流

        输入输出是数据传送的过程,数据像流水一样从一处流向另一处,因此常将输入输出形象地称为流(stream,即数据流。流表示了信息从源到目的端的流动。

 

 C语言文件指针:

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

    定义说明文件指针的一般形式为:

        FILE *指针变量标识符; // 注意FILE应为大写

    例如:FILE *fp; // 表示fp是指向FILE结构的指针变量

 

 文件使用方式

    r  打开一个已存在的文件,准备从文件中读取数据。不能向文件写数据

    w  创建一个新文件,准备向文件写入数据。不能从文件中读取数据。如果文件已经存在,这个文件将被覆盖(先删后建)

    a  打开一个已存在的文件,准备在文件尾部追加数据。不能从文件中读取数据。如果文件不存在,则创建这个文件准备写入数据

    r+ 打开一个已存在的文件,准备读写。既可以读取数据,也可以写入数据

    w+ 创建一个新文件,准备读写。如果文件已经存在,则覆盖原文件

    a+ 等价于a,但可以从文件中读数据

    t  打开一个文本文件

    b  打开一个二进制文件

 

文件基本操作示例:


#include <stdio.h>


int main(int argc, const char * argv[]) {

    // 定义文件指针

    FILE *fp = NULL; // FILE 结构体类型的指针

    

    // 打开文件

    fp = fopen("a.txt", "r"); // r是操作方式,会到Products文件夹查找a.txt文件

    

    // fopen成功,返回文件的首地址,

    // fopen失败,返回NULL

    // 一般我们会做一个判断,当文件打开成功,我们再读写文件

    if (fp != NULL) {

        // 操作文件

        printf("文件打开成功!");

    } else {

        //给用户一个提示

        printf("文件打开失败!按任意键退出。\n");

        //按任意键退出

        getchar(); // 要求从键盘接收一个字符

        //退出

        exit(1); // 非正常退出

    }

    return 0;

}



 2.字符的读写函数fputc和fgetc

    fputc() 写入一个字符到文件中

    fgetc() 读取一个字符到变量中


fputc()的使用:把'x'写入到fputc.txt


#include <stdio.h>


int main(int argc, const char * argv[]) {

    // 1.定义文件指针

    FILE *fp = NULL;

    

    // 2.w方式打开fputc.txt

    fp = fopen("fputc.txt", "w");

    

    // 3.判断是否打开成功

    if (fp != NULL) {

        // 4.如果打开成功,要写入字符

        fputc('x', fp);

        printf("文件写入成功\n");

    }

    

    // 5.关闭文件指针

    fclose(fp);

    

    //fgetc()的使用

    FILE *fp1 = fopen("fputc.txt", "r");

    char ch = fgetc(fp1);

    printf("%c\n",ch);

    

    return 0;

}



fputc fgetc 的使用:读写一个字符串

#include <stdio.h>

#include <string.h>


int main(int argc, const char * argv[]) {

    // 定义一个字符串

    char ch[] = "i want join itheima !";

    

    // 定义文件指针

    FILE *fp1 = NULL;

    FILE *fp2 = NULL;

    

    // w方式打开fputs.txt

    fp1 = fopen("fputcstring.txt", "w");

    

    // 判断是否打开成功

    if (fp1 != NULL) {

        // 如果打开成功,则逐字符写入字符串

        for (int i = 0; i < strlen(ch); i ++) {

            fputc(ch[i], fp1);

        }

        printf("文件写入成功\n");

    }

    

    // 关闭文件指针1

    fclose(fp1);

    

    // r方式打开fputs.txt

    fp2 = fopen("fputcstring.txt", "r");

    

    // 判断是否打开成功

    if (fp2 != NULL) {

        // 如果打开成功,先读取第一个字符

        char c = fgetc(fp2);

        

        // 判断读取的字符是不是文件的末尾

        while (c != EOF) { // EOF是文件的末尾标志

            // 如果读取的字符不是文件末尾,则输出该字符

            putchar(c);

            // 继续从文件中读取下一个字符

            c = fgetc(fp2);

        }

    }

    printf("\n文件读取成功");

    

    return 0;

}


应用实例:从键盘输入一行字符,将其写入一个文件,再把该文件内容读出显示在屏幕上。

#include <stdio.h>


int main(int argc, const char * argv[]) {

    // 定义变量

    char ch;

    FILE *fp = NULL;

    

    // 打开文件

    fp = fopen("a.txt", "w+");

    

    // 判断是否打开成功

    if (fp != NULL) {

        // 如果成功,提示输入字符串

        printf("请输入字符串:\n");

        

        // 接收字符串

        ch = getchar();

        

        //循环写入文件

        while (ch != '\n') { // ch不等于回车时

            fputc(ch, fp); // ch写入文件

            ch = getchar(); // 将下一个字符赋值给ch

        }

    }

    

    // 读出该文件内容

    rewind(fp); // 将文件指针重新指向文件首地址

    ch = fgetc(fp); // 读取第一个字符

    while (ch != EOF) { // ch不等于文件末尾

        putchar(ch); // 输出ch

        ch = fgetc(fp); // 继续读取下一字符

    }


    // 关闭指针

    fclose(fp);

    return 0;

}



3.字符串读写函数fputs和fgets

 fputs函数的功能是向指定的文件写入一个字符串。

 其调用形式为:fputs(字符串,文件指针); // 其中字符串可以是字符串常量,也可以是字符数组名,或指针变量。

 如:fputs("abcd",fp); // 其意义是把字符串“abcd”写入fp所指的文件中

 

 fgets函数的功能是从指定的文件中读一个字符串到字符数组中。

 函数的调用形式为:fgets(字符数组名, n, 文件指针); // 其中n是一个正整数,表示从文件中读出的字符串不超过n-1个字符。fgets在读取的时候,遇到\nEOF,读取结束,并会在读入的最后一个字符后加上字符串结束标志'\0'

 例如:fgets(str, n, fp); // 其意义是从fp所指的文件中读出n-1个字符送入字符数组str中。


使用示例:

#include <stdio.h>


int main(int argc, const char * argv[]) {

    // 定义一个字符数组

    char str[] = " I want join itheima !";

    

    // 定义一个文件指针

    FILE *fp = NULL;

    

    // 打开文件

    fp = fopen("b.txt", "w+");

    

    // 判断是否打开成功

    int count = 0;

    if (fp != NULL) {

        // 如果打开成功,写入字符串

        count = fputs(str, fp);

        printf("成功写入了%d个字符\n",count);

    }

    

    // 读取字符串

    rewind(fp); // 重置文件指针

    char str1[100]; // 定义字符数组

    fgets(str1, sizeof(str1), fp); // fp所指文件中读取字符到str1

    printf("%s",str1); // 打印str1

    

    // 关闭指针

    fclose(fp);

    return 0;

}



 4.数据块读写函数freadfwrite

    C语言还提供了用于整块数据的读写函数。可用来读写一组数据,如一个数组元素,一个结构变量的值等。

 读数据块函数调用的一般形式为:fread(buffer,size,count,fp);

 写数据块函数调用的一般形式为:fwrite(buffer,size,count,fp);

 其中:

 buffer:是一个指针,在fread函数中,它表示存放输入数据的首地址。在fwrite函数中,它表示存放输出数据的首地址。

 size:表示数据块的字节数。

 count:表示要读写的数据块块数。

 fp:表示文件指针。

 例如:

    fread(fa, 4, 5, fp); // 其意义是从fp所指的文件中,每次读取4个字节(一个实数)送入数组fa中,连续读5次,即读5个实数到fa中。


// fwritefread使用举例

#include <stdio.h>

#include <string.h>


int main(int argc, const char * argv[]) {

    // 定义字符串

    char *str = "I want join itheima!";

    

    // 定义文件指针并打开文件

    FILE *fp = fopen("fwrite.txt", "w+");

    

    // 判断是否打开成功

    if (fp != NULL) {

        // 如果打开成功,则写入数据块

        fwrite(str, strlen(str), 1, fp); // str地址开始,每次写入strlen(str)个字节,写入1次到fp所指文件中

    }

    

    // 读取数据块

    rewind(fp); // 重置文件指针

    char str1[100]; // 定义数组用来存放读取的字符串

    fread(str1, 1, 100, fp); // fp所指文件中,每次读取1个字节送入数组str1中,连续读取100次。

    printf("%s", str1); // 打印str1的内容

    

    // 关闭指针

    fclose(fp);

    return 0;

}



应用:从文件中读取结构体信息

//实现:从键盘输入两个学生数据,写入一个文件中,再读出这两个学生的数据显示在屏幕上。

#include <stdio.h>


//定义学生结构体

typedef struct{

    char name[21];

    int age;

    float score;

} Student;

int main(int argc, const char * argv[]) {

    // 定义学生数组

    Student stu[2];

    

    // 提示用户输入学生1的信息

    printf("请依次输入学生1的姓名,年龄和分数,用空格隔开:\n");

    

    // 接收用户输入的信息,并赋值给学生1

    scanf("%s %d %f",&stu[0].name, &stu[0].age, &stu[0].score);

    

    // 提示用户输入学生2的信息

    printf("请依次输入学生2的姓名,年龄和分数,用空格隔开:\n");


    // 接收用户输入的信息,并赋值给学生2

    scanf("%s %d %f",&stu[1].name, &stu[1].age, &stu[1].score);


    // 定义文件指针

    FILE *fp = NULL;

    

    // 打开文件

    fp = fopen("students.data", "wb+");

    

    // 判断是否打开成功

    if (fp != NULL) {

        // 将学生数据写入文件

        fwrite(&stu[0], sizeof(stu[0]), 2, fp);

    }

    

    // 读出学生数据

    rewind(fp);

    Student stu2[2];

    fread(stu2,sizeof(stu2[0]), 2, fp);

    

    // 打印学生数据

    for (int i = 0; i < 2; i ++) {

        printf("学生%d的姓名:%s 年龄:%d 分数:%.2f \n", i+1, stu2[i].name, stu2[i].age, stu2[i].score);

    }

    

    // 关闭指针

    fclose(fp);

    

    return 0;

}



 5.格式化读写函数fscanffprintf

    fscanf函数和fprintf函数与前面使用的scanfprintf函数的功能相似,都是格式化读写函数。两者的区别在于fscanf函数和fprint函数的读写对象不是键盘和显示器,而是磁盘文件。

 这两个函数的调用格式为:

    fscanf(文件指针,格式字符串,输入表列);

    fprintf(文件指针,格式字符串,输出表列);

 

使用示例:

#include <stdio.h>


int main(int argc, const char * argv[]) {

    // 定义文件指针并打开文件

    FILE *fp = fopen("fprintf.txt", "w+");

    

    // 判断是否打开成功

    if (fp != NULL) {

        int a = 2;

        int b = 3;

        // 按一定格式写入

        fprintf(fp, "%d lalala &&* %d", a,b);

    }

    

    rewind(fp); // 重置文件指针

    

    //定义变量

    int m = 0, n = 0;

    char c;

    // 按一定格式输出

    fscanf(fp, "%d lalal%c &&* %d", &m, &c, &n);

    printf("m = %d, n = %d, c = %c", m, n, c);

    

    // 关闭指针

    fclose(fp);

    return 0;

}



应用:读取和写入一个二维数组

// 使用fprintffscanf函数将一个二维数组逐行写入到文件中,并读取出来。

// 1,2#

// 3,4#

// 5,6#

#include <stdio.h>


int main(int argc, const char * argv[]) {

    // 定义并初始化一个二维数组

    int arr[3][2] = {1,2,3,4,5,6};

    

    // 定义文件指针,并打开文件

    FILE *fp = fopen("h.txt", "w+");

    

    // 如果打开成功,则写入文件

    if (fp != NULL) {

        for (int i = 0; i < 3; i ++) {

            fprintf(fp, "%d,%d#\n", arr[i][0],arr[i][1]);

        }

    }

    

    // 重置文件指针

    rewind(fp);

    

    // 定义数组

    int arr1[3][2];

    

    // 按格式读取文件

    for (int i = 0; i <3; i ++) {

        fscanf(fp, "%d,%d#", &arr1[i][0], &arr1[i][1]);

    }

    

    // 打印输出

    for (int i = 0; i < 3; i ++) {

        printf("%d,%d#\n",arr1[i][0],arr1[i][1]);

    }

    return 0;

}



 6.文件的随机读写

    为了只读写文件中某一指定部分,而不是从头开始读写,我们可以移动文件内部的位置指针到需要读写的位置,再进行读写,这种读写称为随机读写。实现随机读写的关键是要按要求移动位置指针,这称为文件的定位。

 文件定位

    移动文件内部位置指针的函数主要有两个,即rewind()fseek()

    1)rewind的功能是把文件内部的位置指针移到文件首。

        其调用形式为: rewind(文件指针);

    2)fseek函数用来移动文件内部位置指针。

        其调用形式为:

            fseek(文件指针,位移量,起始点);

            其中:

                 “文件指针指向被移动的文件。

                 "位移量"表示移动的字节数,要求位移量是long型数据,以便在文件长度大于64KB时不会出错。当用常量表示位移量时,要求后缀“L”

                 "起始点"表示从何处开始计算位移量,规定的起始点有三种:文件首(用符号SEEK_SET或数字0表示),当前位置(用符号SEEK_CUR或数字1表示)和文件尾(用符号SEEK_END或数字2表示)。

        例如: fseek(fp, 100L,0); // 其意义是把位置指针移到离文件首100个字节处。

        还要说明的是fseek函数一般用于二进制文件。在文本文件中由于要进行转换,故往往计算的位置会出现错误。


// 读取student.data文件中第二个学生的信息

#include <stdio.h>


// 定义学生结构体

typedef struct{

    char name[21];

    int age;

    float score;

} Student;


int main(int argc, const char * argv[]) {

    // 定义文件指针,并打开文件

    FILE *fp = fopen("students.data", "r");

    

    // 判断是否打开成功

    if (fp != NULL) {

        // 定义变量用于存放学生信息

        Student stu;

        

        //移动文件指针到第二个学生信息的首地址

        fseek(fp, sizeof(stu), SEEK_SET);

        

        // 读取student.data文件中第二个学生信息

        fread(&stu, sizeof(stu), 1, fp);

        

        // 打印第二个学生的信息

        printf("学生2的姓名:%s 年龄:%d 分数:%.2f \n", stu.name, stu.age, stu.score);

    }

    

    // 关闭文件指针

    fclose(fp);


    return 0;

}



7.文件检测函数

1.文件结束检测函数feof函数

    调用格式:

        feof(文件指针);

    功能:判断文件是否处于文件结束的位置,如文件结束,则返回值为1,否则为0

 2.读写文件出错检测函数

    ferror(文件指针);

    功能:检查文件在用各种输入输出函数进行读写时是否出错。如ferror返回值为0表示未出错,否则表示有错。

 3.文件出错标志和文件结束标志置0函数

    clearerr(文件指针);

    功能:本函数用于清除出错标志和文件结束标志,使它们为0值。


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值