Linux软件编程(三)文件操作-文件 I/O
一、文件 I/O 基础
文件 I/O 是 Linux 内核 提供给应用层的一套文件操作方法,直接通过系统调用实现,移植性相对较弱,但能精确控制文件和硬件的读写。
基本流程:
打开文件 —
open
读/写文件 —
read
/write
关闭文件 —
close
二、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);
功能:打开文件并获得文件描述符(fd)
参数:
pathname
:文件路径flags
:打开方式O_RDONLY
:只读O_WRONLY
:只写O_RDWR
:可读可写O_CREAT
:创建文件O_TRUNC
:清空文件O_APPEND
:追加写
mode
:文件权限(仅在O_CREAT
时有效)例如
0664
表示rw-rw-r--
实际权限 =
mode & ~umask
返回值:
成功:文件描述符(非负整数)
失败:-1
三、文件描述符
是内核为已打开文件分配的标识符,类型为小的非负整数
范围:
0 ~ 1023
(Linux 默认支持 1024 个打开文件)分配原则:最小未使用优先
0、1、2 已被占用:
0
→ 标准输入(stdin)1
→ 标准输出(stdout)2
→ 标准错误(stderr)
标准 I/O 与文件 I/O 对比:
标准 I/O | 文件 I/O |
---|---|
FILE * | int fd |
缓冲区 | 无缓冲区 |
四、close 函数
#include <unistd.h>
int close(int fd);
功能:关闭文件,释放文件描述符
返回值:
成功:0
失败:-1
五、write 函数
ssize_t write(int fd, const void *buf, size_t count);
功能:向文件写入 count
字节数据
参数:
fd
:文件描述符buf
:数据首地址count
:写入字节数
六、read 函数
ssize_t read(int fd, void *buf, size_t count);
功能:从文件读取 count
字节数据
返回值:
成功:实际读取字节数
读到文件末尾:0
失败:-1
七、lseek 函数(文件定位)
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:调整文件读写位置
参数:
fd
:文件描述符offset
:偏移量(字节)whence
:SEEK_SET
:文件开头SEEK_CUR
:当前位置SEEK_END
:文件末尾
示例:获取文件大小
off_t len = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET); // 复位
八、标准 I/O 与文件 I/O 对比
标准 I/O:
属于 C 库函数,跨平台
封装了系统调用,带缓冲区(效率高)
常用于普通文件操作
文件 I/O:
属于系统调用,仅适用于 Linux
无缓冲区
常用于硬件或特殊文件
九、缓冲区类型
行缓冲(1KB)
常用于交互式终端
刷新条件:
'\n'
、缓冲区满、fflush()
、程序结束
全缓冲(4KB)
常用于文件
刷新条件:缓冲区满、
fflush()
、文件关闭、程序结束
无缓冲(0KB)
常用于
stderr
十、练习题
用文件 I/O 实现
cat
功能:./a.out filename
该代码是一个简单的C语言程序,用于读取指定文件内容并输出到标准输出(屏幕)。程序通过命令行参数接收文件路径,以只读方式打开文件并逐块读取内容。
代码分析
#include "head.h"
#include <unistd.h>int main(int argc, char const *argv[])
{if(argc != 2){printf("usager : <a.out> <des>\n");return -1;}int fd = open(argv[1], O_RDONLY);if(fd < 0){printf("open errrr\n");return -1;}char buff[1024] = {0};while(1){ssize_t ret = read(fd, buff, sizeof(buff));if(ret == 0){break;}write(1, buff,ret);}puts("");close(fd);return 0;
}
用文件 I/O 实现文件拷贝:
./a.out srcfile dstfile
#include "head.h"int main(int argc, char const *argv[])
{if(argc != 3){printf("usager : <a.out> <src> <des>\n");return -1;}int fdsrc = open(argv[1], O_RDONLY);int fddes = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0664);if(fdsrc < 0 || fddes < 0){printf("open error\n");return -1;}char buff[1024] = {0};while(1){ssize_t ret = read(fdsrc, buff, sizeof(buff));if(ret == 0){break;}write(fddes, buff, ret);}close(fddes);close(fdsrc);return 0;
}