linux应用编程(一) ———— 文件IO

一、文件IO基础

1、文件描述符

当调用 open 函数打开一个现有文件或创建一个新文件时,内核会向进程返回一个文件描述符,用于指代被打开的文件,所有执行 IO 操作的系统调用都是通过文件描述符来索引到对应的文件,文件描述符是一个非负整数

2、open 打开文件

open 函数用于打开文件,当然除了打开已经存在的文件之外,还可以创建一个新的文件,函数原型如下所示:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

pathname:要打开的文件名(含路径,缺省为当前路径)
flags:O_RDONLY(以只读方式打开文件) O_WRONLY(以只写方式打开文件) O_RDWR(以可读可写方式打开文件)
当我们附带了权限后,打开的文件就只能按照这种权限来操作。
以上者这三个常数中应当只指定一个。下列常数是可选择的:
O_CREAT O_EXCL O_APPEND O_TRUNC …
mode:一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限

在这里插入图片描述
这些宏既可以单独使用,也可以通过位或运算将多个宏组合在一起

3、write 写文件

调用 write 函数可向打开的文件写入数据

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

fd:文件描述符。
buf:指定写入数据对应的缓冲区。
count:指定写入的字节数。

4、read 读文件

调用 read 函数可从打开的文件中读取数据

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

fd:文件描述符。与 write 函数的 fd 参数意义相同。
buf:指定用于存储读取数据的缓冲区。
count:指定需要读取的字节数。

5、close 关闭文件

可调用 close 函数关闭一个已经打开的文件

#include <unistd.h>
int close(int fd);

fd:文件描述符,需要关闭的文件所对应的文件描述符。
返回值:如果成功返回 0,如果失败则返回-1。

6、leek

读写偏移量用于指示 read()或 write()函数操作时文件的起始位置,会以相对于文件头部的位置偏移量来表示,文件第一个字节数据的位置偏移量为 0。

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

fd:文件描述符。
offset:偏移量,以字节为单位。
whence:用于定义参数 offset 偏移量对应的参考值,该参数为下列其中一种(宏定义)
⚫ SEEK_SET:读写偏移量将指向 offset 字节位置处(从文件头部开始算);
⚫ SEEK_CUR:读写偏移量将指向当前位置偏移量 + offset 字节位置处,offset 可以为正、也可以为负,如果是正数表示往后偏移,如果是负数则表示往前偏移;
⚫ SEEK_END:读写偏移量将指向文件末尾 + offset 字节位置处,同样 offset 可以为正、也可以为负,如果是正数表示往后偏移、如果是负数则表示往前偏移。

返回值:成功将返回从文件头部开始算起的位置偏移量(字节为单位),也就是当前的读写位置;发生错误将返回-1。

二、深入探究文件 I/O

1、返回错误处理与 errno

当程序中调用函数发生错误的时候,操作系统内部会通过设置程序的 errno 变量来告知调用者究竟发生了什么错误!errno 本质上是一个 int 类型的变量,用于存储错误编号。

#include <stdio.h>
#include <errno.h>
int main(void)
{
printf("%d\n", errno);
return 0;
}

这里介绍一个 C 库函数strerror(),该函数可以将对应的 errno 转换成适合我们查看的字符串信息,其函数原型如下所示

#include <string.h>
char *strerror(int errnum);

errnum:错误编号 errno。
返回值:对应错误编号的字符串描述信息。

除了 strerror 函数之外,我们还可以使用 perror 函数来查看错误信息,一般用的最多的还是这个函数,调用此函数不需要传入 errno,函数内部会自己去获取 errno 变量的值,调用此函数会直接将错误提示字符串打印出来,而不是返回字符串,除此之外还可以在输出的错误提示字符串之前加入自己的打印信息,函数原型如下所示

#include <stdio.h>
void perror(const char *s);

s:在错误提示字符串信息之前,可加入自己的打印信息,也可不加,不加则传入空字符串即可。
返回值:void 无返回值。

2、exit、_exit、_Exit

在 Linux 系统下,进程正常退出除了可以使用 return 之外,还可以使用 exit()、_exit()以及_Exit(),下面我们分别介绍

main 函数中使用 return 后返回,return 执行后把控制权交给调用函数,结束该进程。调用_exit()函数会清除其使用的内存空间,并销毁其在内核中的各种数据结构,关闭进程的所有文件描述符,并结束进程、将控制权交给操作系统。_exit()函数原型如下所示:

#include <unistd.h>
void _exit(int status);

调用函数需要传入 status 状态标志,0 表示正常结束、若为其它值则表示程序执行过程中检测到有错误发生。

_Exit()函数原型如下所示:

#include <stdlib.h>
void _Exit(int status);

_exit()和_Exit()两者等价,用法作用是一样的

exit()函数_exit()函数都是用来终止进程的,exit()是一个标准 C 库函数,而_exit()和_Exit()是系统调用。执行 exit()会执行一些清理工作,最后调用_exit()函数。exit()函数原型如下:

#include <stdlib.h>
void exit(int status);

该函数是一个标准 C 库函数,使用该函数需要包含头文件<stdlib.h>,该函数的用法和_exit()/_Exit()是一样的

二、标准 I/O库

1、FILE 指针

对于标准 I/O 库函数来说,它们的操作是围绕 FILE 指针进行的,当使用标准 I/O 库函数打开或创建一个文件时,会返回一个指向 FILE 类型对象的指针(FILE *),所以由此可知,FILE 指针的作用相当于文件描述符

2、打开文件 fopen()

在文件 I/O 中,使用 open()系统调用打开或创建文件,而在标准 I/O 中,我们将使用库函数fopen()打开或创建文件,fopen()函数原型如下所示

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

path:参数 path 指向文件路径,可以是绝对路径、也可以是相对路径。
mode:参数 mode 指定了对该文件的读写权限,是一个字符串。
返回值:调用成功返回一个指向 FILE 类型对象的指针(FILE *)

调用 fclose()库函数可以关闭一个由 fopen()打开的文件,其函数原型如下所示:

#include <stdio.h>
int fclose(FILE *stream);

参数 stream 为 FILE 类型指针,调用成功返回 0;失败将返回 EOF(也就是-1),并且会设置 errno 来指示错误原因。

3、读文件和写文件

当使用 fopen()库函数打开文件之后,接着我们便可以使用 fread()和 fwrite()库函数对文件进行读、写操作了,函数原型如下所示:

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

库函数 fread()用于读取文件数据,其参数和返回值含义如下:
ptr:fread()将读取到的数据存放在参数 ptr 指向的缓冲区中;
size:fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大小为 nmemb * size 个字节。
nmemb:参数 nmemb 指定了读取数据项的个数。
stream:FILE 指针。
返回值:调用成功时返回读取到的数据项的数目

库函数 fwrite()用于将数据写入到文件中,其参数和返回值含义如下:
ptr:将参数 ptr 指向的缓冲区中的数据写入到文件中。
size:参数 size 指定了每个数据项的字节大小,与 fread()函数的 size 参数意义相同。
nmemb:参数 nmemb 指定了写入的数据项个数,与 fread()函数的 nmemb 参数意义相同。
stream:FILE 指针。
返回值:调用成功时返回写入的数据项的数目

4、fseek 定位

库函数 fseek()的作用类似于系统调用 lseek(),用于设置文件读写位置偏移量,lseek()用于文件 I/O,而库函数 fseek()则用于标准 I/O,其函数原型如下所示:

#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);

stream:FILE 指针。
offset:与 lseek()函数的 offset 参数意义相同。
whence:与 lseek()函数的 whence 参数意义相同。
返回值:成功返回 0;发生错误将返回-1,并且会设置 errno 以指示错误原因;与 lseek()函数的返回值意义不同,这里要注意!

库函数 ftell()可用于获取文件当前的读写位置偏移量,其函数原型如下所示:

#include <stdio.h>
long ftell(FILE *stream);

参数 stream 指向对应的文件,函数调用成功将返回当前读写位置偏移量;调用失败将返回-1,并会设置errno 以指示错误原因。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值