从零开始的敲代码生活--Linux应用软件(文件操作基础2)

一、文件IO

文件IO是Linux内核提供的文件操作接口,属于系统调用。 核心接口:open()read()write()close()

1. 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:打开方式标志位,可以多标志位按位或组合
flags 含义
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
O_CREAT 文件不存在则创建
O_TRUNC 打开时清空文件内容
O_APPEND 追加模式,写在文件末尾

标准IO mode 和 文件IO flags对应关系

标准IO mode 文件IO flags
"r" O_RDONLY
"r+" O_RDWR
"w" O_WRONLY | O_TRUNC | O_CREAT,0664
"w+" O_RDWR | O_TRUNC | O_CREAT,0664
"a" O_WRONLY | O_CREAT | O_APPEND,0664
"a+" O_RDWR | O_CREAT | O_APPEND,0664
  • mode:新建文件权限,实际权限 = mode & ~umask;普通文件常用0664,满权限0777

返回值:成功返回文件描述符,失败返回-1

文件描述符 打开文件后内核分配的非负小整数;范围默认0‑1023,共1024个;分配规则:取当前最小未被使用的编号。 系统默认已经打开:

标准IO 文件IO文件描述符宏
stdin 0(STDIN_FILENO)
stdout 1(STDOUT_FILENO)
stderr 2(STDERR_FILENO)

2. close 关闭文件

复制代码
#include <unistd.h>
int close(int fd);

参数:fd为文件描述符。 返回:成功0,失败‑1

注意:打开后必须关闭,否则发生文件描述符泄漏。

3. write 写数据

复制代码
ssize_t write(int fd, const void *buf, size_t count);
  • fd:文件描述符
  • buf:待写入数据缓冲区首地址
  • count:期望写入字节数 返回:成功返回实际写入字节数;失败返回‑1

4. read 读数据

复制代码
ssize_t read(int fd, void *buf, size_t count);
  • fd:文件描述符
  • buf:存放读取数据的缓冲区
  • count:期望读取字节数 返回:成功返回实际读到字节数;读到文件末尾返回0;失败返回‑1

5. read + write 实现文件拷贝

复制代码
int file_copy(const char *srcfile, const char *dstfile)
{
    int fdsrc = open(srcfile, O_RDONLY);
    int fddst = open(dstfile, O_WRONLY | O_CREAT | O_TRUNC, 0664);
    if (-1 == fdsrc || -1 == fddst)
    {
        printf("open error\n");
        return -1;
    }
    char buff[1024] = {0};
    ssize_t size = 0;
    while ((size = read(fdsrc, buff, sizeof(buff))) > 0)
    {
        write(fddst, buff, size);
    }
    close(fdsrc);
    close(fddst);
    return 0;
}

6. lseek 文件定位

复制代码
off_t lseek(int fd, off_t offset, int whence);
  • offset:偏移字节数
  • whence偏移基准:
    • SEEK_SET:文件开头
    • SEEK_CUR:当前读写位置
    • SEEK_END:文件末尾 返回:成功返回当前距离文件开头偏移量;失败返回‑1

二、文件IO和标准IO的区别

对比项 标准IO 文件IO
操作对象 FILE *(文件流指针) fd(文件描述符int)
函数来源 C库函数,可移植性强 Linux系统调用,可移植弱
缓冲区 用户层带缓冲区,减少系统调用,效率高 无用户层缓冲区,实时性好
适用场景 普通文件读写 普通文件、硬件设备文件

缓冲区分类

  1. 行缓冲:终端交互,默认1024字节;\n、程序结束、fflush、缓冲区满触发刷新。
  2. 全缓冲:普通文件,默认4096字节;关闭文件、程序结束、缓冲区满、fflush触发刷新。
  3. 无缓冲:stderr标准错误输出,直接输出。

三、目录IO

目录操作API:opendirreaddirclosedirmkdir

1. opendir 打开目录

复制代码
DIR *opendir(const char *name);

参数:目录名;返回目录流指针;失败返回NULL

2. closedir 关闭目录

复制代码
int closedir(DIR *dirp);

返回成功0,失败‑1

3. readdir 读取目录项

复制代码
struct dirent *readdir(DIR *dirp);

返回struct dirent*,读到目录末尾/出错返回NULL

复制代码
struct dirent {
    ino_t d_ino;         /* inode编号 */
    off_t d_off;
    unsigned short d_reclen;
    unsigned char d_type;/* 文件类型 */
    char d_name[256];    /* 文件名 */
};

4. mkdir 创建目录

复制代码
int mkdir(const char *pathname, mode_t mode);

参数:目录名,目录权限;成功返回0,失败‑1

创建文件对比:

  • mkdir:创建文件夹
  • touch命令:创建普通文件
  • open() / fopen():代码内创建普通文件

目录遍历示例代码

遍历/dev目录,过滤隐藏文件,打印文件名与inode号

复制代码
int main(void)
{
    DIR *pdir = opendir("/dev");
    if (NULL == pdir)
    {
        printf("opendir error\n");
        return -1;
    }
    while (1)
    {
        struct dirent *pinfo = readdir(pdir);
        if (NULL == pinfo)
        {
            break;
        }
        if ('.' == pinfo->d_name[0])
        {
            continue;
        }
        printf(" %s : %ld\n", pinfo->d_name, pinfo->d_ino);
    }
    closedir(pdir);
    return 0;
}

四、其他常用接口

1. 格式化输出系列

复制代码
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int dprintf(int fd, const char *format, ...);
int sprintf(char *str, const char *format, ...);
  • printf:输出到标准输出stdout
  • fprintf:格式化输出到文件流FILE*
  • dprintf:格式化输出到文件描述符fd
  • sprintf:格式化输出到内存字符数组,常用于数字转字符串、字符串拼接

2. strtok 字符串分割

复制代码
char *strtok(char *str, const char *delim);

功能:按分隔符delim切割字符串;第一次传入原字符串,后续调用传NULL;返回分割得到子串首地址;分割完毕返回NULL

⚠会修改原字符串。

3. 出错处理函数

复制代码
char *strerror(int errnum);
void perror(const char *s);
  • strerror:将错误码errno转为错误信息字符串。
  • perror:打印自定义提示字符串 + 系统错误原因。
相关推荐
Sunqk566525 分钟前
将开发板串口连接到Ubuntu后未找到对应的设备文件?
linux·运维·ubuntu
Sophnet云平台27 分钟前
MCP与A2A双协议解析:2026年Agent互操作的技术选型
linux·服务器·网络·上下文·mcp·大模型测评·sophnet
晚风叙码30 分钟前
Linux(二)权限问题
linux·服务器
BI专家之路2 小时前
安装linux/hadoop/jdk/hive
linux·hive·hadoop
GeW15 小时前
超详细!RHCE10版通用备考策略,内含评分细则解读
linux
用户0413284651316 小时前
Linux 服务开机自启动怎么配置?systemctl enable 原理详解
linux
草莓熊Lotso1 天前
【Redis 初阶】Set 类型深度解析:去重集合的运算能力与实战场景
linux·网络·数据库·windows·redis·tcp/ip·缓存
张文君1 天前
ubuntu26.04坏道坏块分区隔离急速版260831-V0.12
linux·python
贝锐1 天前
从国产化信创设备到商用安卓终端,向日葵如何帮助企业实现统一运维管理?
linux·运维·远程控制