标准C库对文件的操作——fopen、fread、fwrite的简单使用及open、read、write区别

本文详细比较了C语言中fopen、fread、fwrite与open、read、write之间的区别,涉及文件描述符、移植性、适用范围、缓冲与非缓冲文件系统以及它们在IO层次中的位置,帮助读者明确何时选择哪种方法进行文件操作。
摘要由CSDN通过智能技术生成

fopen、fread、fwrite及open、read、write区别

一、fopen和open的区别

(1)来源

open是UNIX系统调用函数(包含LINUX等),返回的是文件描述符(File Description),它是文件在文件描述符表里的索引。

fopen是ANSIC标准中的C语言库函数,在不同的系统中应调用不同的内核API,返回一个指向文件结构的指针。

(2)移植性

这一点从上面的来源就可以推断出来,‘fopen’是C标准函数,因此拥有良好的移植性;而‘open’是UNIX系统调用的,移植性有限。如:windows下相似的功能使用API函数‘CreateFile’。

(3)适用范围

open返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等,也包括操作普通正规文件(Regular File)

fopen是用来操作普通正规文件(Regular File)

(4)缓冲/非缓冲文件系统

1、缓冲文件系统

缓冲文件系统是借助于文件结构体指针 FILE* 来对文件进行管理,通过文件指针对文件进行访问,即可以读写字符、字符串、格式化数据,也可以读写二进制数据

缓冲文件系统特点:

在内存中开辟一个“缓冲区”,为程序里每一个文件使用,当执行读文件操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依次读入接收的变量。执行写文件操作时,也是先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外在的次数,内存“缓冲区”越大,则操作外存的次数就越少,执行速度就越快,效率就越高。一般来说,文件“缓冲区”的大小跟机器是相关的。

缓冲文件系统的IO函数主要包括:

fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等

2、非缓冲文件系统

  • 非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出
  • 它不设文件结构体指针,只能读写二进制文件(对于UNIX系统内核而言,文本文件和二进制代码文件并无区别),但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此,在读取正规的文件时,建议大家最好不要选择它。

非缓冲文件系统的IO函数主要包括:

open, close, read, write, getc, getchar, putc, putchar等

(5)文件IO层次

open:低级IO函数

fopen:高级IO函数

高低级根据谁离系统内核更近

低级:运行在内核态

高级:运行在用户态

(6)补充

对缓冲和非缓冲文件系统的补充,举个例子来更清晰的了解什么情况下用缓冲,什么情况下用非缓冲的

如果文件的大小是8k。

你如果用read/write,且只分配了2K的缓存,则要将此文件读出需要做4次系统调用来实际从磁盘上读出。如果你用fread/fwrite,则系统自动分配缓存,则读出此文件只要一次系统调用从磁盘上读出。也就是用read/write要读4次磁盘,而用fread/fwrite则只要读1次磁盘。效率比read/write要高4倍。

如果程序对内存有限制,则用read/write比较好。都用fread 和fwrite,它自动分配缓存,速度会很快,比自己来做要简单。

如果要处理一些特殊的文件,用read 和write,如 套接口,管道之类的设备文件。

系统调用write的效率取决于你buffer的大小和你要写入的总数量,如果buffer太小,你进入内核空间的次数大增,效率就低下。而fwrite会替你做缓存,减少了实际出现的系统调用,所以效率比较高。

二、fread、fwrite和read、write的区别

(1)fread、fwrite是带缓冲的,read、write不带缓冲

fopen、fread、fwrite的简单应用

一、fopen函数

头文件:

#include <stdio.h>

函数:

FILE *fopen(const char *path, const char *mode);

第一个参数:文件路径

第二个参数:以什么权限访问文件

权限                                                                                        二进制文件

r:只读打开文本文件                                                                rb

r+:可读可写打开文本文件                                                       rb+

w:只写打开文本文件                                                              wb

w+:可读可写方式创建一个文本文件                                      wb+

a:追加方式打开文本文件                                                        ab

a+:可读可写可追加的方式打开一个文本文件                         ab+

二、fread函数

头文件

#include <stdio.h>

函数

size_t fread(void *ptr, size_t size, size_t nmenb, FILE *stream)

第一个参数:是读取的数据存放的内存的指针, (可以是数组,也可以是新开辟的空间)

第二个参数:是每次读取的字节数

第三个参数:是读取的次数

第四个参数:是要读取的文件的指针

返回值

成功:是实际读取的元素(并非字节)数目,当目标缓冲区是20字节时,而读100次,返回的是实际读到有字节的次数。

失败:返回0

三、fwrite函数

头文件

#include <stdio.h>

函数

size_t fwrite(const void *ptc, size_t size, size_t nmenb, FILE *stream);

第一个参数:是读取的数据存放的内存的指针, (可以是数组,也可以是新开辟的空间)

第二个参数:是每次读取的字节数

第三个参数:是读取的次数

第四个参数:是要读取的文件的指针

返回值:

成功,该函数返回一个 size_t 对象,表示元素的总数(其实就是nmemb),该对象是一个整型数据类型。如果该数字与 nmemb 参数不同,则会显示一个错误。

失败:返回0

四、fseek函数

头文件

#include <stdio.h>

函数

int fseek( FILE *stream, long offset, int origin );
第一个参数:stream为文件指针
第二个参数:offset为偏移量,整数表示正向偏移,负数表示负向偏移
第三个参数:origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2


返回值:

成功返回0

失败返回非0

五、其他

fputc函数:

int fputc(int c, FILE *stream);
参数:
    c:字符
    fp:文件指针
返回值:
    成功:返回写入的字符
    失败:返回EOF

fputs函数:
int fputs(const char *s, FILE *stream);
参数:
    s:字符串
    fp:文件指针
返回值:
    成功:返回非负数
    失败:返回EOF

fgetc函数:

int fgetc(FILE *stream);

从文件fp中读入一个字节,指针自动后移

为什么fgetc返回的是int而不是char?
通过man fgetc查看其返回值:fgetc(), getc() and getchar() return the character read as an unsigned char cast to an int or EOF on end of file or error.
返回时,unchar型会被转换为int,因为读到文件尾时需要返回的是EOF(-1), 如果为char型,-1与0XFF相等,会发生冲突


返回值:

成功,则返回读取的“字节”,同于fputc函数的 ch,到达文件尾,返回EOF结束

fgets函数

char * fgets(char *str, int n, FILE *fp)

从文件中每次读入一行。
str是存放将要读入字符型数据的存放地址
n是数目变量
fp是文件指针


该函数表明从文件fp中读入n-1个字符放在以str为起始地址的空间
因为系统会在最后加上一个‘\0’。

读入过程中:
若该行字符数不超过n-2个(2代表该行本身的换行符‘\n’和系统自动加上的'\0')
则函数读完该行就结束,文件指针移动到下一行,再进行文件读入操作时,从下一行开始读入。

若该行字符数目总数(不包含换行符)大于n-2,则只读入n-1个字符(1代表系统自己加上的'\0')
文件指针自动移动到下一个字符处,再进行文件读入操作时,顺序读入该行剩下的字符。

返回值:
文件读入成功则返回str

失败或者读到文件尾则返回null

feof 函数

int feof(FILE *stream);
feof()是检测流上的文件结束符的函数,如果文件结束,则返回非0值,否则返回0
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值