C语言实现文件读写操作的几种常用方法

 更新时间:2024年03月07日 10:08:43   作者:dlpmmk  
C语言提供了一系列文件操作函数,使得我们可以通过程序对文件进行读写操作,本文主要介绍了C语言实现文件读写操作的几种常用方法,具有一定的参考价值,感兴趣的可以了解一下

一 、文件读写的常用函数

(1) 读写文本文件:

读文本文件 :一般都使用 getc 、fgets 、fscanf 函数

使用getc读文件

#include <stdio.h>
int main()
{
    char a[20] = "a.txt";
    FILE *p = fopen(a,"r");
    if(p)
    {
        char c;
        while(1)
        {
            c = getc(p);
            if(c == EOF)
                break;
            printf("%c",c);
        }
        printf("\n");
        fclose(p);
    }
    else
    {
        printf("fail\n");
    }
    return 0;
}

使用fgets读文件

#include <stdio.h>
int main()
{
    FILE *p = fopen("test.txt","r");
    if(p == NULL)
        return 0;
    char temp[1024];
    fgets(temp,sizeof(temp),p);
    while(!feof(p))
    {
        printf("%s",temp);
        fgets(temp,sizeof(temp),p);
    }
    fclose(p);
    return 0;
}

使用fscanf读文件

#include <stdio.h>
int main()
{
    FILE *p = fopen("a.txt", "r");
    if(p == NULL)
    {
        printf("the file is close!");
        return 0;
    }
    char str1[200], str2[200], str3[200];
    int year;
    int status = fscanf(p, "%s %s %s %d", str1, str2, str3, &year); 
    while(!feof(p))
    {
        printf("%s %s %d %d status = %d\n", str1, str2, str3, year, status);
        status = fscanf(p, "%s %s %s %d", str1, str2, str3, &year);
    }
    fclose(p);
    return 0;
}

写文本文件 :一般都使用 putc 、 fputs、fprintf 函数

使用putc写文件

#include <stdio.h>
int main()
{
    FILE *p = fopen("a.txt","w");
    if(p)
    {
        putc('h',p);
        fclose(p);
    }
    return 0;
}

使用fputs写文件

#include <stdio.h>
int main()
{
    FILE *p = fopen("abc.c","w");
    if(p)
    {
        fputs("#include <stdio.h>\nint main()\n{\nprintf(\"hello world\\n\");\nreturn 0;\n}",p);
        fclose(p);
    }
    return 0;
}

使用fprintf写文件

#include <stdio.h>
#include <string.h>
int main()
{
    FILE *p = fopen("a.txt","w");
    char buf[1024];
    fgets(buf, sizeof(buf), stdin);
    while(strcmp(buf,"exit\n") != 0)
    {
       fprintf(p, "%s", buf);
       fgets(buf, sizeof(buf), stdin); 
    }
    fclose(p);
    return 0;
}

(2) 读写二进制文件

读二进制文件: 使用fread 函数

代码:

#include <stdio.h>
void readFile()
{
    FILE *p = fopen("a.txt", "rb");
    char buf[20] = { 0 };
    int index = 0;
    while(1)
    {
        int res = fread(buf, 1, 5, p);
        printf("res = %d , ", res);
        if(feof(p))
            break;
        printf("buf = %s\n",buf);
        index++;
    }
    fclose(p);
    printf("%d\n", index);
}
int main()
{
    readFile();
    return 0;
}

写二进制文件: 使用fwrite 函数

代码

#include <stdio.h>
void writeFile()
{
    FILE *p = fopen("b.txt", "w");
    char buf = 'a';
    int i;
    for(i = 0; i < 10 ; i++)
    {
        fwrite(&buf, 1, 1, p);
        buf++;
    }
    fclose(p);
}
int main()
{
    writeFile();
    return 0;
}

二、文件读写的深层次的剖析

(1)操作系统与硬件储存

众所周知,我们的计算机操作系统都是由C语言写的,通过C语言协调物理内存与虚拟内存,操作系统想要向物理内存中写数据的时候,会费很大的力。

写数据到物理内存

当操作系统有一个字节的数据想要写入物理磁盘中,首先要经历一下几个步骤:

  • 调用CPU的控制器,发出存储请求。
  • 控制器把将要存储的数据放入临时寄存器。
  • 查看总线是否被占用,请求总线控制。
  • 往地址总线发送将要使用的一个字节的空间指定。
  • 讲数据寄存器中数据发送到数据总线上,传输到先一步找到的物理地址。
  • 存储完毕,释放总线。

从磁盘中读数据

读数据的操作与写数据的操作正好相反,也是要经历总线请求与总线释放的过程。

总之,操作系统想要往磁盘中读写数据要经历很繁琐的过程。

(2)操作系统封装读写数据函数接口

每次操作系统与磁盘进行数据交互的时候,都会对CPU有一系列的操作指令,这些读写指令的合集就是读写函数,通过C语言实现这些读写函数再往外部抛出一系列的接口,就实现的读写数据的函数封装。

当用户想往磁盘中写入数据的时候只需要调用这些函数接口就行了。

然而这些函数都是针对最底层的数据存储操作,不利于计算机的操作性能提高,所以,有人就在这层函数的基础上再次进行封装,把性能更加好,更加优化的读写数据函数封装到C语言的标准库中。

在标准库中的读写数据函数,例如fwrite和fputs等等。它们不是每次写入一个字节数据就往物理磁盘中写入数据,而是利用函数在内存中开辟出一个固定大小的字节缓冲池,通过这个缓冲池,来实现数据的读与写。

(3)C语言中的数据缓冲池

C语言的所有读写函数,都会使用到数据缓冲池,无论是读数据操作,还是写数据操作,都会把数据临时存储到这里。

写数据

当我们使用C语言往文件中写入一个字节的数据的时候,会经历一下几个步骤:

  • 使用函数往目标文件中写入一个字节的数据。
  • 数据被存储在内存的数据缓冲池中。
  • 关闭要写入的文件。
  • 底层函数把缓冲池中的数据写入磁盘中。

从上面的步骤中可以看出我们的函数在执行到写入数据的操作的时候,数据并没有真正的写入到磁盘中,而是等到写入文件的操作结束的时候,才把数据缓冲池中的数据写入磁盘中。

同样的我们使用C语言读一个字节数据的时候,同样会经历一下步骤:

  • 打开要读的文件。
  • 底层函数从磁盘中读取满整个缓冲池的数据。
  • 关闭要读的文件。
  • 从缓冲池中读取要读取的字节数,剩余没用的数据不读。

缓冲池工作原理

当知道我们的所有读写操作都要进入缓冲池时,我们同样要知道缓冲池的工作原理。

  • 缓冲池有一定固定的大小
  • 缓冲池在进行读数据的操作时,如果要读取的数据字节小于缓冲池的大小,缓冲池会从磁盘中读取满整个缓冲池的数据,所以当每次读取的字节数过小,读取次数过多的时候,会减少访问实际磁盘的磁盘,增加程序运行的性能。
  • 缓冲池的刷新,每刷新一次都会进行与实际物理内存的交互。

当缓冲池满了或者目标操作文件关闭的时候,缓冲池会自动刷新,写数据时,缓冲池的数据会进入物理磁盘;读数据时,缓冲池的数据会数据固定字节的数据进入输出终端。

总而言之,缓冲池仅仅是用户与物理磁盘之间数据交户的一个缓冲而已,不用想的太深奥。

三、使用函数刷新缓冲池

fflush函数:

函数作用:

刷新缓冲池

函数定义:

int fflush(FILE *P);

参数 返回值:

  • P:目标操作文件
  • 返回值:如果成功,该函数返回零值。如果发生错误,则返回 EOF 。

使用示例:

现有空文件a.txt

利用标准输入数据,在文件没有关闭的时候,查看文件内是否有写入的数据。

#include <stdio.h>
#include <string.h>
void write_file()
{
    FILE *p = fopen("a.txt", "w");
    char temp[100] = { 0 };
    while(1)
    {
        fgets(temp, sizeof(temp), stdin);
        if(strcmp(temp, "exit\n") == 0)
            break;
        fprintf(p, "%s", temp);
    }
    fclose(p);
}
int main()
{
    write_file();
    return 0;
}

运行结果:

输入中

[文件]$ gcc -o a fflush.c
[文件]$ a
hello

查看文件a.txt

可以看到文件为空,输入的文件现在正存储在缓冲池中。

输入exit退出输入,查看文件a

[文件]$ cat a.txt
hello

文件关闭,缓冲池中的数据写入磁盘。

现在我们创建一个函数使每输入一次都写入一次磁盘:

#include <stdio.h>
#include <string.h>
void write_file()
{
    FILE *p = fopen("a.txt", "w");
    char temp[100] = { 0 };
    while(1)
    {
        fgets(temp, sizeof(temp), stdin);
        if(strcmp(temp, "exit\n") == 0)
            break;
        fprintf(p, "%s", temp);
        fflush(p);
    }
    fclose(p);
}
int main()
{
    write_file();
    return 0;
}

运行结果:

输入中,查看a.txt

[文件]$ gcc -o a fflush.c
[文件]$ a
hello

再开启另一个终端查看文件 a.txt 状态:

[文件]$ cat a.txt
hello

输入结束,查看a.txt

[文件]$ a
hello
exit
[文件]$ cat a.txt
hello
[文件]$ 

可以看到使用fflush函数把缓冲池中的数据写入了磁盘。

四、总结

当我们在往磁盘中录入重要的非常重要的数据的时候,一定要使用fflush不断的刷新缓冲池,因为数据非常重要;但我们输入不重要的数据是一定要尽量减少使用fflush函数的次数,因为那样会让程序变得缓慢。

到此这篇关于C语言实现文件读写操作的几种常用方法的文章就介绍到这了,更多相关C语言 文件读写操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++ 自定义栈实现迷宫求解

    C++ 自定义栈实现迷宫求解

    这篇文章主要介绍了C++ 自定义栈实现迷宫求解的相关资料,需要的朋友可以参考下
    2017-07-07
  • 如何实现一定概率选中某一个字母

    如何实现一定概率选中某一个字母

    本篇文章是对如何实现一定概率选中某一个字母的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C++并查集亲戚(Relations)算法实例

    C++并查集亲戚(Relations)算法实例

    这篇文章主要介绍了C++并查集亲戚(Relations)算法,实例分析了并查集亲戚算法的原理与实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04
  • C语言实现对文件进行操作的示例详解

    C语言实现对文件进行操作的示例详解

    这篇文章主要为大家详细介绍了C语言实现对文件进行操作的相关知识,文中的示例代码讲解详细,对我们学习C语言有一定的帮助,需要的可以参考一下
    2023-04-04
  • C语言实现BMP图像的读写功能

    C语言实现BMP图像的读写功能

    这篇文章主要介绍了C语言实现BMP图像的读写功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • C语言深入讲解语句与选择结构的使用

    C语言深入讲解语句与选择结构的使用

    这篇文章主要为大家介绍了C语言的语句与选择结构,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • C语言实现bmp图像对比度扩展

    C语言实现bmp图像对比度扩展

    这篇文章主要为大家详细介绍了C语言实现bmp图像对比度扩展,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • C++空间命名的使用

    C++空间命名的使用

    本文主要介绍了C++空间命名的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • C++ opencv霍夫圆检测使用案例详解

    C++ opencv霍夫圆检测使用案例详解

    这篇文章主要介绍了C++ opencv霍夫圆检测使用案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • C语言使用DP动态规划思想解最大K乘积与乘积最大问题

    C语言使用DP动态规划思想解最大K乘积与乘积最大问题

    Dynamic Programming动态规划方法采用最优原则来建立用于计算最优解的递归式,并且考察每个最优决策序列中是否包含一个最优子序列,这里我们就来展示C语言使用DP动态规划思想解最大K乘积与乘积最大问题
    2016-06-06

最新评论