【Linux系统编程】open()函数和fopen函数的对比,相关函数的使用

Linux文件编程

open()函数和fopen的对比

  1. 来源
    从来源的角度看,两者能很好的区分开,这也是两者最显而易见的区别:
    open是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引。
    fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。
    PS:从来源来看,两者是有千丝万缕的联系的,毕竟C语言的库函数还是需要调用系统API实现的。

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

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

  4. 文件IO层次
    如果从文件IO的角度来看,前者属于低级IO函数,后者属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。

  5. 缓冲
    缓冲文件系统
    缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器 而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等。
    非缓冲文件系统
    缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open, close, read, write, getc, getchar, putc, putchar等。

一句话总结一下,就是open无缓冲,fopen有缓冲。前者与read, write等配合使用, 后者与fread,fwrite等配合使用。
使用fopen函数,由于在用户态下就有了缓冲,因此进行文件读写操作的时候就减少了用户态和内核态的切换(切换到内核态调用还是需要调用系统调用API:read,write);而使用open函数,在文件读写时则每次都需要进行内核态和用户态的切换;表现为,如果顺序访问文件,fopen系列的函数要比直接调用open系列的函数快;如果随机访问文件则相反。

open()

open 是一个系统调用函数,位于 unistd.h 头文件中。它用于打开一个文件,并返回一个文件描述符,该描述符是一个非负整数,标识已打开文件的唯一标识。

基本语法
在这里插入图片描述
参数说明

  • Pathname:要打开的文件名(含路径,缺省为当前路径)

  • Flags:

     O_RDONLY 只读打开         O_WRONLY 只写打开         O_RDWR  可读可写打开
    

    当我们附带了权限后,打开的文件就只能按照这种权限来操作。
    以上这三个常数中应当只指定一 个。下列常数是可选择的:

     O_CREAT 若文件不存在则创建它。使用此选项时,需要同时说明第三个参数mode,用其说明该新文件的存取许可权限。
     O_EXCL 如果同时指定了OCREAT,而文件已经存在,则出错。        
     O_APPEND 每次写时都加到文件的尾端。
     O_TRUNC 属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0。
    
  • Mode:一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限

代码演示

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main()
{
	int fd;
	
	fd = open("./file1",O_RDWR);

	if(fd == -1){
		printf("open file1 failed\n");
		fd = open("./file1",O_RDWR|O_CREAT,0600);
		if(fd > 0){
			printf("create file1 success!\n");
		}
	}
	return 0;
}

结果
在这里插入图片描述

write()、 read()、lseek()、 close()函数

write 函数用于向文件描述符指向的文件写入数据

基本语法
在这里插入图片描述
参数说明

fd:文件描述符。它是由 open 函数返回的,用于标识已打开的文件。
buf:指向要写入的数据的指针。
count:要写入的字节数。

返回值:

成功时返回实际写入的字节数。
失败时返回 -1,并设置 errno 来指示错误类型

read 函数用于从文件描述符指向的文件读取数据。

参数说明:

fd:文件描述符。它是由 open 函数返回的,用于标识已打开的文件。
buf:指向存储读取数据的缓冲区。
count:要读取的字节数。

返回值:

成功时返回实际读取的字节数。若返回 0,表示已到达文件末尾。
失败时返回 -1,并设置 errno 来指示错误类型。

在这里插入图片描述

lseek 函数用于重新定位文件描述符的读写位置,常用于随机访问文件中的特定位置。
将文件读写指针相对whence移动offset个字节

在这里插入图片描述

参数说明:

fd:文件描述符。它是由 open 函数返回的,用于标识已打开的文件。
offset:偏移量,以字节为单位。偏移量的解释方式取决于 whence 参数。
whence:基准位置,有以下三种取值:
SEEK_SET:文件开头。offset 即为绝对偏移量。
SEEK_CUR:当前位置。offset 为相对于当前文件位置的偏移量。
SEEK_END:文件末尾。offset 为相对于文件末尾的偏移量。

返回值:

成功时返回新的文件偏移量(以字节为单位)。
失败时返回 (off_t) -1,并设置 errno 来指示错误类型。

close 函数用于关闭一个已打开的文件描述符,并释放相关的资源。

参数说明:

fd:文件描述符。它是由 open 函数返回的,用于标识已打开的文件。

返回值:

成功时返回 0。
失败时返回 -1,并设置 errno 来指示错误类型。

代码演示

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main()
{
	int fd;
	char *buf = "hello world !";	

	fd = open("./file1",O_RDWR);

	if(fd == -1){
		printf("open file1 failed\n");
		fd = open("./file1",O_RDWR|O_CREAT,0600);
		if(fd > 0){
			printf("create file1 success!\n");
		}
	}
	
	printf("open susceess : fd = %d\n",fd);
//	ssize_t write(int fd, const void *buf, size_t count);
	int n_write = write(fd,buf,strlen(buf));
	if(n_write != -1){
		printf("write %d byte to file\n",n_write);
	}

//	close(fd);

//	fd = open("./file1",O_RDWR);
//	off_t lseek(int fd, off_t offset, int whence);

	char *readBuf;
	readBuf = (char *)malloc(sizeof(char)*n_write + 1);	
//	  ssize_t read(int fd, void *buf, size_t count);
	lseek(fd, -n_write, SEEK_CUR);

	int n_read = read(fd, readBuf,100);
	
	printf("read %d ,context:%s\n",n_read,readBuf);
	close(fd);

	return 0;
}

结果
在这里插入图片描述

fopen()

在 C 语言中,fopen、fread、fwrite、fseek 和 fclose 是标准库函数,用于文件操作

fopen 函数用于打开一个文件,并返回一个指向 FILE 结构体的指针,用于后续的文件操作。

#include <stdio.h>

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

参数说明

filename:文件的路径。
mode:文件打开模式,常用的模式有:
"r":以只读模式打开文件。
"w":以只写模式打开文件,若文件存在则清空文件内容。
"a":以追加模式打开文件。
"r+":以读写模式打开文件。
"w+":以读写模式打开文件,若文件存在则清空文件内容。
"a+":以读写追加模式打开文件。

返回值

成功时返回一个指向 FILE 结构体的指针。
失败时返回 NULL。

fread()、fwrite()、fseek()、fclose()函数

fread 函数用于从文件中读取数据

#include <stdio.h>

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

参数说明:

ptr:指向存储读取数据的缓冲区。
size:每个数据单元的大小,以字节为单位。
nmemb:要读取的数据单元的个数。
stream:指向已打开文件的 FILE 指针。

返回值:

成功时返回实际读取的数据单元的个数。
失败时返回一个小于 nmemb 的值,并设置 ferror。

fwrite 函数用于向文件中写入数据。

基本语法:

#include <stdio.h>

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

参数说明:

ptr:指向要写入的数据的缓冲区。
size:每个数据单元的大小,以字节为单位。
nmemb:要写入的数据单元的个数。
stream:指向已打开文件的 FILE 指针。

返回值:

成功时返回实际写入的数据单元的个数。
失败时返回一个小于 nmemb 的值,并设置 ferror。

fseek 函数用于重新定位文件指针的位置。

基本语法:

#include <stdio.h>

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

参数说明:

stream:指向已打开文件的 FILE 指针。
offset:偏移量,以字节为单位。偏移量的解释方式取决于 whence 参数。
whence:基准位置,有以下三种取值:
SEEK_SET:文件开头。offset 即为绝对偏移量。
SEEK_CUR:当前位置。offset 为相对于当前文件位置的偏移量。
SEEK_END:文件末尾。offset 为相对于文件末尾的偏移量。

返回值:

成功时返回 0。
失败时返回 -1。

fclose 函数用于关闭一个已打开的文件,并释放相关的资源。

基本语法:

#include <stdio.h>

int fclose(FILE *stream);

参数说明

stream:指向已打开文件的 FILE 指针。

返回值

成功时返回 0。
失败时返回 EOF,并设置 errno 来指示错误类型。
  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值