小田

V1

2023/02/04阅读:23主题:橙心

C/C++之fopen

前言

在我们需求开发中,经常需要读取文件的内容,在C++中,通常使用open/close或者fopen/fclose来完成这个功能,那么open与fopen有什么异同呢,在开发中我们应当如何选择这两个函数呢,我们一起来看一下。

1.fopen和open的区别

  1. 来源不同
  • open是unix系统调用函数,其返回值是文件描述符,是文件描述符表里的索引值。
  • fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核API,返回的是一个指向文件结构的指针。
  1. 可移植性
  • fopen是C标准函数,具有良好的可移植性。
  • open是unix系统调用,可移植性有限。
  1. 使用范围

    open返回文件描述符,文件描述符是unix下同下的重要概念,在unix系统下,对一切设备都是以文件的形式进行操作,除了Regular文件之外,其他比如网络套接字,硬件设备等都是以文件的形式操作。

  2. 文件IO层次

    从文件IO的角度来看,open属于低级IO函数,fopen属于高级IO函数,低级和高级的简单区分标准是与系统内核的距离,即open距离系统内核较近,运行在内核态,fopen距离系统内核较远,运行在用户态。

  3. 是否有缓冲区

    open没有缓冲区,fopen有缓冲区

  • 缓冲文件系统

    在内存开辟一个"缓冲区",为程序中的每一个文件使用,当执行文件读操作时,将磁盘上的文件数据先读入内存"缓冲区",当缓冲区被装满后再从缓冲区依次读入接收的变量。执行写文件的操作时,先将数据写入内存"缓冲区",待内存缓冲区装满后再写入文件。所以,内存缓冲区的大小影响着实际操作外存的次数,内存缓冲区越大,则操作外存的次数就越少,用户态与内核态的切换越少,执行速度就越快,效率高,文件缓冲区的大小随机器而定。fopen具有缓冲区。

  • 非缓冲文件系统

    缓冲文件系统借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,即可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级别的输入输出,每次调用都需要进行用户态与内核态的切换,它不设文件结构体指针,只能读写二进制文件,但效率高,速度快,但是由于ANSIC标准不再包括非缓冲文件系统,因此不建议使用没有缓冲区的函数。open没有缓冲区。

2.常用缓冲区函数

fopen/fclose

/*
*path 文件,
FILE *fp 返回值
*mode 模式
       "r"           打开文字文件只读
       "w"           创建文字文件只写
       "a"           增补, 如果文件不存在则创建一个
       "r+"          打开一个文字文件读/写
       "w+"          创建一个文字文件读/写
       "a+"          打开或创建一个文件增补
       "b"           二进制文件(可以和上面每一项合用)
       "t"           文这文件(默认项)
————————————————
*/

 #include <stdio.h>
 FILE *fopen(const char *path, const char *mode);
 int fclose(FILE *fp);

fread/fwrite

#include <stdio.h>

/*
从stream所指向的文件中读取数据块,读取的字节数为size*nmemb,读取来的数据存放在buffer为起始地址的内存中。若fread函数的返回值等于nmemb,则执行本函数读取数据成功;若文件结束或发生错误,返回值等于0。
ptr:存放数据的内存起始地址
size:数据块的大小
nmemb:读取数据块的数量
fp:文件结构体指针
*/

 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  
  /*
  fwrite:将内存中从ptr地址开始的数据往stream所指向的文件里写,写入到文件里的字节数为size*nmemb。返回值同上。
  */

 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

/*
fseek用于重定位流(数据流/文件)上的文件内部位置指针的位置。
stream :文件FILE
offset :偏移量
whence  : 1、SEEK_SET  光标移至头
          2、SEEK_END  光标移至尾巴
          3、SEEK_CUR  光标当前位置
*/

int fseek(FILE *stream, long offset, int whence);

/*
ftell 用于得到文件位置指针当前位置相对于文件首的偏移字节数

stream:指向 FILE 对象的指针,该 FILE 对象标识了流.
*/

long ftell(FILE *stream);

/*
rewind 将文件内部的位置指针重新指向一个流(数据流/文件)的开头。
stream:指向 FILE 对象的指针,该 FILE 对象标识了流.
*/

void rewind(FILE *stream);

3.IO函数示例

读取文件内容到字符串

    FILE* ini = fopen(AuBackUpIni, "r");
    if(!ini) {
        printf("open %s failed\n", AuBackUpIni);
        return false;
    }
    fseek(ini, 0, SEEK_END);
    size_t size = ftell(ini);
    char* where = new char[size];
    rewind(ini);
    fread(where, sizeof(char), size, ini);
    printf("where=%s\n", where);
   fclose(ini);

写字符串到文件

FILE* fp = fopen(versionFilePath, "w");
    if(!fp) {
        printf("open %s file failed\n", versionFilePath);
        return false;
    }
    fprintf(fp, "%s", versionInfo);
    fclose(fp);

这就是本篇文章要跟大家分享的内容,希望大家每天坚持进步~

给个赞支持一下,谢谢啦~

分类:

后端

标签:

后端

作者介绍

小田
V1