文件 IO
一、总述
Linux 中除网口外 “一切皆文件”,文件操作分为两类:标准文件 IO(C 语言标准库函数)和系统文件 IO(操作系统直接提供的接口)。
二、标准文件 IO
定义:基于 C 语言标准库的文件操作函数,封装了底层细节。
核心函数(含功能、参数、返回值):
函数名 | 功能说明 | 参数 | 返回值 |
---|---|---|---|
fopen | 以指定方式打开文件 | path(文件路径及名)、mode(打开方式,如 r、w、a 等) | 成功返回 FILE 指针,失败返回 NULL 且设置 errno |
fread | 读取文件数据 | ptr(存储数据的地址)、size(每次读取字节数)、nmemb(读取次数)、stream(FILE 指针) | 返回完整读取的 nmemb 数 |
fwrite | 向文件写入数据 | ptr(待写入数据地址)、size(每次写入字节数)、nmemb(写入次数)、stream(FILE 指针) | 返回完整写入的 nmemb 数 |
fclose | 关闭文件 | stream(待关闭的 FILE 指针) | 成功返回 0,失败返回 EOF 且设置 errno |
fseek | 移动文件指针 | stream(FILE 指针)、offset(偏移字节数)、whence(基准位置:SEEK_SET/SEEK_CUR/SEEK_END) | 成功返回 0,失败非 0 |
ftell | 获取当前文件指针位置 | stream(FILE 指针) | 返回相对于文件头的字节数 |
rewind | 将文件指针定位到文件开头 | stream(FILE 指针) | 无返回值(等效于 fseek (stream, 0, SEEK_SET)) |
remove | 删除指定文件 | pathname(文件路径) | 成功返回 0,失败返回 - 1 |
rename | 重命名文件 | old(原名称)、new(新名称) | 成功返回 0,失败返回 - 1 |
其他常用函数:fputc、fputs、putc、putchar、puts(写入字符 / 字符串);fgetc、fgets、getc、getchar(读取字符 / 字符串)。
三、系统文件 IO
定义:操作系统直接提供的接口,直接与内核交互。
核心函数:open、read、write、close(文档未详细说明参数及返回值,仅列出名称)。
四、标准文件 IO 与系统文件 IO 的差异
对比项 | 标准文件 IO | 系统文件 IO |
---|---|---|
缓存机制 | 默认使用缓冲区,数据先写入缓冲区,满足条件后执行实际操作;作用是减少系统调用次数,提升效率 | 无默认缓冲区,每次操作均为系统调用,效率较低 |
跨平台性 | 接口由 C 标准定义,与操作系统无关,同一代码可跨平台运行,跨平台性强 | 接口由操作系统决定,不可跨平台 |
操作对象 | 操作对象为FILE*(封装了文件描述符、缓冲区等信息) | Linux 下操作对象为文件描述符,Windows 下为句柄 |
使用场景 | 通常用于用户态下的操作 | 一般用于底层设备驱动文件等控制 |
关键问题
问题:标准文件 IO 和系统文件 IO 的核心差异体现在哪些方面?两者的效率为何有差异? 答案:核心差异体现在四方面:①缓存机制(标准 IO 有默认缓冲区,系统 IO 无);②跨平台性(标准 IO 强,系统 IO 弱);③操作对象(标准 IO 为 FILE*,系统 IO 在 Linux 下为文件描述符);④使用场景(标准 IO 用于用户态,系统 IO 用于底层控制)。效率差异源于缓存机制:标准 IO 通过缓冲区减少系统调用次数,降低内核态与用户态切换开销,因此效率更高;系统 IO 每次操作直接调用内核,开销大,效率较低。
问题:使用 fopen 函数时,不同打开方式(r、w、a 等)的核心区别是什么? 答案:fopen 的打开方式决定了文件的操作权限和指针初始位置:①r/r+:只读 / 读写,文件必须存在,指针始于文件头;②w/w+:只写 / 读写,文件不存在则创建,存在则清空,指针始于文件头;③a/a+:追加 / 读 + 追加,文件不存在则创建,写操作指针始于文件尾,a + 的读操作指针始于文件头。
问题:在实际开发中,如何选择使用标准文件 IO 还是系统文件 IO? 答案:需根据场景判断:①若需跨平台开发(如同时适配 Linux 和 Windows),优先选标准文件 IO;②若操作底层设备(如驱动文件)或需要直接与内核交互,选择系统文件 IO;③若追求用户态操作效率(减少系统调用),标准文件 IO 更合适;④若需精确控制 IO 过程(无缓存干扰),可选用系统文件 IO。