Linux文件IO与目录IO编程深度解析:从系统调用到实战应用

目录

[1 文件IO编程基础](#1 文件IO编程基础)

[1.1 文件IO与标准IO的区别](#1.1 文件IO与标准IO的区别)

[1.2 文件描述符概念](#1.2 文件描述符概念)

[2 文件IO核心函数详解](#2 文件IO核心函数详解)

[2.1 文件打开函数open](#2.1 文件打开函数open)

[2.2 文件关闭函数close](#2.2 文件关闭函数close)

[2.3 文件写入函数write](#2.3 文件写入函数write)

[2.4 文件读取函数read](#2.4 文件读取函数read)

[2.5 文件定位函数lseek](#2.5 文件定位函数lseek)

[3 文件IO实战应用](#3 文件IO实战应用)

[3.1 图片文件拷贝示例](#3.1 图片文件拷贝示例)

[3.2 文件大小统计程序](#3.2 文件大小统计程序)

[4 目录IO编程](#4 目录IO编程)

[4.1 目录操作核心函数](#4.1 目录操作核心函数)

[4.1.1 打开目录opendir](#4.1.1 打开目录opendir)

[4.1.2 关闭目录closedir](#4.1.2 关闭目录closedir)

[4.1.3 读取目录项readdir](#4.1.3 读取目录项readdir)

[4.2 目录创建与删除](#4.2 目录创建与删除)

[4.2.1 创建目录mkdir](#4.2.1 创建目录mkdir)

[4.2.2 删除目录rmdir](#4.2.2 删除目录rmdir)

[4.3 目录遍历实战示例](#4.3 目录遍历实战示例)

[4.4 工作目录操作](#4.4 工作目录操作)

[4.4.1 切换工作目录chdir](#4.4.1 切换工作目录chdir)

[4.4.2 获取当前目录getcwd](#4.4.2 获取当前目录getcwd)

[5 时间相关接口](#5 时间相关接口)

[5.1 时间获取函数](#5.1 时间获取函数)

[5.1.1 获取当前时间time](#5.1.1 获取当前时间time)

[5.1.2 时间转换localtime](#5.1.2 时间转换localtime)

[5.1.3 时间生成mktime](#5.1.3 时间生成mktime)


1 文件IO编程基础

1.1 文件IO与标准IO的区别

文件IO(文件输入输出)是Linux系统编程中直接使用系统调用的IO方式,与标准IO相比具有以下特点:

核心差异

  • 缓存机制:文件IO无缓存,标准IO有缓存

  • 函数类型:文件IO是系统调用,标准IO是库函数

  • 适用场景:文件IO适合设备文件、通信文件,标准IO适合普通文件

  • 性能特点:文件IO实时性强,标准IO效率高

系统调用与库函数关系

  • 系统调用:Linux内核提供的底层接口

  • 库函数:对系统调用的封装,提供更友好的接口

1.2 文件描述符概念

文件描述符是Linux内核为每个打开文件分配的唯一标识符,是一个非负整数。系统默认打开三个文件描述符:

  • 0:标准输入(stdin)

  • 1:标准输出(stdout)

  • 2:标准错误(stderr)

文件描述符特性

  • 有上限限制(可通过ulimit -n查看)

  • 新描述符选择最小未使用的非负整数

  • 进程结束时自动关闭所有打开的文件描述符

2 文件IO核心函数详解

2.1 文件打开函数open

cpp 复制代码
#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:打开标志位

  • mode:文件权限(创建文件时使用)

常用flags标志

cpp 复制代码
O_RDONLY    // 只读
O_WRONLY    // 只写  
O_RDWR      // 读写
O_CREAT     // 文件不存在则创建
O_TRUNC     // 文件存在则截断清空
O_APPEND    // 追加模式
O_EXCL      // 与O_CREAT配合,文件存在则报错

权限模式示例

cpp 复制代码
0664    // rw-rw-r--
0777    // rwxrwxrwx

open与fopen模式对应关系

cpp 复制代码
"r"   -> O_RDONLY
"r+"  -> O_RDWR
"w"   -> O_WRONLY | O_CREAT | O_TRUNC, 0664
"w+"  -> O_RDWR | O_CREAT | O_TRUNC, 0664
"a"   -> O_WRONLY | O_CREAT | O_APPEND, 0664
"a+"  -> O_RDWR | O_CREAT | O_APPEND, 0664

2.2 文件关闭函数close

cpp 复制代码
#include <unistd.h>

int close(int fd);

关闭文件描述符,释放系统资源。成功返回0,失败返回-1。

2.3 文件写入函数write

cpp 复制代码
#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

参数说明

  • fd:文件描述符

  • buf:写入数据缓冲区

  • count:要写入的字节数

返回值

  • 成功:实际写入的字节数

  • 失败:-1

2.4 文件读取函数read

cpp 复制代码
#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

参数说明

  • fd:文件描述符

  • buf:读取数据缓冲区

  • count:最大读取字节数

返回值

  • 成功:实际读取的字节数

  • 文件末尾:0

  • 失败:-1

2.5 文件定位函数lseek

cpp 复制代码
#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

whence参数

cpp 复制代码
SEEK_SET    // 文件开头
SEEK_CUR    // 当前位置
SEEK_END    // 文件末尾

特殊用法

cpp 复制代码
lseek(fd, 0, SEEK_END);    // 获取文件大小
lseek(fd, 0, SEEK_SET);    // 回到文件开头

3 文件IO实战应用

3.1 图片文件拷贝示例

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(void)
{
    int fp1 = 0;
    int fp2 = 0;
    char tmpbuff[1024] = {0};
    ssize_t nret = 0;

    fp1 = open("ssr.bmp",O_RDONLY);
    if(-1 == fp1)
    {
        perror("fail to open");
        return -1;
    }
    fp2 = open("dst.bmp",O_WRONLY | O_CREAT | O_TRUNC, 0664);
    if(-1 == fp1)
    {
        perror("fail to open");
        return -1;
    }

    while (1)
    {
        nret = read(fp1,tmpbuff,sizeof(tmpbuff));
        if(nret == 0)
        {
            break;
        }
        write(fp2,tmpbuff,nret);
    }
    return 0;
}

3.2 文件大小统计程序

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

int main() {
    int fd;
    char filename[256];
    off_t file_size;
    
    printf("请输入文件路径: ");
    scanf("%s", filename);
    
    // 打开文件
    fd = open(filename, O_RDONLY);
    if (fd == -1) {
        perror("文件打开失败");
        return -1;
    }
    
    // 获取文件大小
    file_size = lseek(fd, 0, SEEK_END);
    if (file_size == -1) {
        perror("获取文件大小失败");
        close(fd);
        return -1;
    }
    
    printf("文件大小: %ld 字节 (%.2f KB)\n", 
           file_size, (double)file_size / 1024);
    
    close(fd);
    return 0;
}

4 目录IO编程

4.1 目录操作核心函数

4.1.1 打开目录opendir
cpp 复制代码
#include <dirent.h>

DIR *opendir(const char *name);
4.1.2 关闭目录closedir
cpp 复制代码
#include <dirent.h>

int closedir(DIR *dirp);
4.1.3 读取目录项readdir
cpp 复制代码
#include <dirent.h>

struct dirent *readdir(DIR *dirp);

dirent结构体重要成员

cpp 复制代码
ino_t d_ino;           // 索引节点号
char d_name[256];      // 文件名

4.2 目录创建与删除

4.2.1 创建目录mkdir
cpp 复制代码
#include <sys/stat.h>
#include <sys/types.h>

int mkdir(const char *pathname, mode_t mode);

目录权限说明

  • 读权限(r):查看目录项

  • 写权限(w):在目录中新建/删除文件

  • 执行权限(x):进入目录

4.2.2 删除目录rmdir
cpp 复制代码
#include <unistd.h>

int rmdir(const char *pathname);

只能删除空目录。

4.3 目录遍历实战示例

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>

int main(void)
{
    DIR *dp = NULL;
    struct dirent *pp = NULL;

    dp = opendir(".");
    if (NULL == dp)
    {
        perror("fail to opendir");
        return -1;
    }

    while(1)
    {
        pp = readdir(dp);
        if (NULL == pp)
        {
            break;
        }

        if (pp->d_name[0] == '.')
        {
            continue;
        }

        printf("%s\n", pp->d_name);

    }

    closedir(dp);

    return 0;
}

4.4 工作目录操作

4.4.1 切换工作目录chdir
cpp 复制代码
#include <unistd.h>

int chdir(const char *path);
4.4.2 获取当前目录getcwd
cpp 复制代码
#include <unistd.h>

char *getcwd(char *buf, size_t size);

使用示例

cpp 复制代码
#include <stdio.h>
#include <unistd.h>

int main() {
    char cwd[1024];
    
    if (getcwd(cwd, sizeof(cwd)) != NULL) {
        printf("当前工作目录: %s\n", cwd);
    } else {
        perror("获取当前目录失败");
    }
    
    // 切换目录
    if (chdir("/tmp") == 0) {
        printf("成功切换到 /tmp 目录\n");
    } else {
        perror("切换目录失败");
    }
    
    return 0;
}

5 时间相关接口

5.1 时间获取函数

5.1.1 获取当前时间time
cpp 复制代码
#include <time.h>

time_t time(time_t *tloc);

返回1970年1月1日至今的秒数。

5.1.2 时间转换localtime
cpp 复制代码
#include <time.h>

struct tm *localtime(const time_t *timep);

tm结构体成员

cpp 复制代码
int tm_sec;     // 秒 [0-59]
int tm_min;     // 分 [0-59]  
int tm_hour;    // 时 [0-23]
int tm_mday;    // 日 [1-31]
int tm_mon;     // 月 [0-11]
int tm_year;    // 年(从1900开始)
int tm_wday;    // 星期 [0-6]
int tm_yday;    // 年内天数 [0-365]
int tm_isdst;   // 夏令时标志
5.1.3 时间生成mktime
cpp 复制代码
#include <time.h>

time_t mktime(struct tm *tm);
相关推荐
寻寻觅觅☆8 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
l1t9 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
赶路人儿9 小时前
Jsoniter(java版本)使用介绍
java·开发语言
ceclar12310 小时前
C++使用format
开发语言·c++·算法
码说AI10 小时前
python快速绘制走势图对比曲线
开发语言·python
Gofarlic_OMS10 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
星空下的月光影子10 小时前
易语言开发从入门到精通:补充篇·网络爬虫与自动化采集分析系统深度实战·HTTP/HTTPS请求·HTML/JSON解析·反爬策略·电商价格监控·新闻资讯采集
开发语言
老约家的可汗10 小时前
初识C++
开发语言·c++
wait_luky10 小时前
python作业3
开发语言·python
消失的旧时光-194311 小时前
第十九课:为什么要引入消息队列?——异步系统设计思想
java·开发语言