欢迎光临
我们一直在努力

Linux软件编程:IO编程,文件IO,目录IO,以及一些常用的时间函数接口

一、文件IO(系统调用)

1. 文件IO与标准IO的区别

特性标准IO文件IO
缓存 有缓存(全缓存/行缓存/无缓存) 无缓存
接口类型 库函数 系统调用
适用对象 普通文件 设备文件、通信文件
头文件 <stdio.h> <fcntl.h>, <unistd.h>

2. 文件IO核心接口

a. open – 打开文件

c

#include <fcntl.h>

// 原型
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

// 示例
int fd = open("test.txt", O_RDWR | O_CREAT, 0664);
if (fd == -1) {
perror("open failed");
exit(1);
}

flags参数说明:

  • O_RDONLY: 只读

  • O_WRONLY: 只写

  • O_RDWR: 读写

  • O_CREAT: 文件不存在则创建(需配合mode参数)

  • O_TRUNC: 文件存在则截断为0

  • O_APPEND: 追加模式

  • O_EXCL: 与O_CREAT一起使用,文件存在则报错

mode参数(权限):

  • 八进制表示,如0664表示rw-rw-r–

  • 常用权限:0777(rwxrwxrwx)、0755(rwxr-xr-x)

b. read – 读取文件

c

#include <unistd.h>

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

// 示例
char buffer[1024];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
if (bytes_read == -1) {
perror("read failed");
}

c. write – 写入文件

c

#include <unistd.h>

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

// 示例
char *data = "Hello, File IO!";
ssize_t bytes_written = write(fd, data, strlen(data));
if (bytes_written == -1) {
perror("write failed");
}

d. lseek – 移动文件偏移量

c

#include <unistd.h>

// 原型
off_t lseek(int fd, off_t offset, int whence);

// 示例
// 移动到文件开头
lseek(fd, 0, SEEK_SET);
// 移动到文件末尾
lseek(fd, 0, SEEK_END);
// 向前移动100字节
lseek(fd, 100, SEEK_CUR);

e. close – 关闭文件

c

#include <unistd.h>

close(fd);

3. 文件描述符

  • 文件描述符是一个非负整数,是内核为每个打开文件维护的引用

  • 三个默认打开的文件描述符:

    • 0:标准输入(stdin)

    • 1:标准输出(stdout)

    • 2:标准错误(stderr)

  • 新文件描述符总是选择最小且未被使用的整数

  • 文件描述符有上限限制(可通过ulimit -n查看)

4. 示例:文件拷贝

c

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define BUFFER_SIZE 4096

int main() {
int src_fd, dst_fd;
ssize_t bytes_read;
char buffer[BUFFER_SIZE];

// 打开源文件
src_fd = open("source.jpg", O_RDONLY);
if (src_fd == -1) {
perror("open source failed");
exit(1);
}

// 创建目标文件
dst_fd = open("dest.jpg", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (dst_fd == -1) {
perror("open dest failed");
close(src_fd);
exit(1);
}

// 拷贝数据
while ((bytes_read = read(src_fd, buffer, BUFFER_SIZE)) > 0) {
if (write(dst_fd, buffer, bytes_read) != bytes_read) {
perror("write failed");
break;
}
}

// 关闭文件
close(src_fd);
close(dst_fd);
printf("File copied successfully!\\n");

return 0;
}


二、目录IO

1. 目录操作接口

a. opendir – 打开目录

c

#include <dirent.h>

// 原型
DIR *opendir(const char *name);

// 示例
DIR *dir = opendir("/home/user");
if (dir == NULL) {
perror("opendir failed");
}

b. readdir – 读取目录项

c

#include <dirent.h>

// 原型
struct dirent *readdir(DIR *dirp);

// 示例
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("File: %s\\n", entry->d_name);
}

c. closedir – 关闭目录

c

#include <dirent.h>

closedir(dir);

d. mkdir – 创建目录

c

#include <sys/stat.h>
#include <sys/types.h>

// 创建目录,权限为0755
mkdir("new_dir", 0755);

e. rmdir – 删除空目录

c

#include <unistd.h>

rmdir("empty_dir");

f. chdir – 切换工作目录

c

#include <unistd.h>

chdir("/home/user/documents");

g. getcwd – 获取当前工作目录

c

#include <unistd.h>

char cwd[1024];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
printf("Current dir: %s\\n", cwd);
}

2. dirent结构体详解

c

struct dirent {
ino_t d_ino; // 文件的inode号
off_t d_off; // 目录项在目录流中的偏移
unsigned short d_reclen; // 记录长度
unsigned char d_type; // 文件类型
char d_name[256]; // 文件名
};

文件类型(d_type):

  • DT_REG: 普通文件

  • DT_DIR: 目录

  • DT_LNK: 符号链接

  • DT_CHR: 字符设备

  • DT_BLK: 块设备

  • DT_FIFO: 管道

  • DT_SOCK: 套接字

3. 示例:遍历目录

4.示例:递归遍历目录以及它的子目录(深度优先遍历)


三、时间相关接口

1. 时间获取和转换函数

a. time – 获取当前时间戳

c

#include <time.h>

// 原型
time_t time(time_t *tloc);

// 示例
time_t now;
now = time(NULL); // 获取当前时间戳
printf("Seconds since 1970: %ld\\n", now);

b. localtime – 转换为本地时间

c

#include <time.h>

// 原型
struct tm *localtime(const time_t *timep);

// 示例
time_t now = time(NULL);
struct tm *local_time = localtime(&now);

printf("Local time: %04d-%02d-%02d %02d:%02d:%02d\\n",
local_time->tm_year + 1900, // 年份从1900开始
local_time->tm_mon + 1, // 月份从0开始
local_time->tm_mday,
local_time->tm_hour,
local_time->tm_min,
local_time->tm_sec);

c. mktime – 将tm结构转为时间戳

c

#include <time.h>

// 示例:创建特定日期的时间戳
struct tm time_struct = {0};
time_struct.tm_year = 122; // 2022-1900
time_struct.tm_mon = 0; // 1月
time_struct.tm_mday = 1; // 1日
time_struct.tm_hour = 12;
time_struct.tm_min = 0;
time_struct.tm_sec = 0;

time_t specific_time = mktime(&time_struct);
printf("Specific time: %ld\\n", specific_time);

2. tm结构体详解

c

struct tm {
int tm_sec; // 秒 [0, 60]
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],0=周日
int tm_yday; // 一年中的第几天 [0, 365]
int tm_isdst; // 夏令时标志(正数=启用,0=不启用,负数=未知)
};

3. 示例:文件时间戳操作

c

#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>

int main() {
// 获取当前时间
time_t current_time = time(NULL);
printf("Current timestamp: %ld\\n", current_time);

// 转换为本地时间
struct tm *local = localtime(&current_time);

// 格式化输出
char time_str[100];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S %A", local);
printf("Formatted time: %s\\n", time_str);

// 计算一周后的时间
local->tm_mday += 7;
time_t next_week = mktime(local);

// 时间差计算
double diff = difftime(next_week, current_time);
printf("One week later: %.0f seconds\\n", diff);

return 0;
}


四、总结与关系图

text

┌─────────────────────────────────────────────────────┐
│ Linux IO系统 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 标准IO │ │ 文件IO │ │
│ │ (库函数) │ │ (系统调用) │ │
│ │ • fopen │ │ • open │ │
│ │ • fread │ │ • read │ │
│ │ • fwrite │ │ • write │ │
│ │ • fclose │ │ • close │ │
│ └─────────────┘ └─────────────┘ │
│ │ │ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ 目录IO │ │
│ │ • opendir │ │
│ │ • readdir │ │
│ │ • mkdir │ │
│ │ • rmdir │ │
│ └─────────────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ 时间接口 │ │
│ │ • time │ │
│ │ • localtime │ │
│ │ • mktime │ │
│ └─────────────────────┘ │
│ │
│ 共同特性: │
│ 1. 所有接口都基于"一切皆文件"理念 │
│ 2. 都需要包含相应头文件 │
│ 3. 都需要错误处理(检查返回值) │
│ 4. 都需要管理资源(关闭/释放) │
└─────────────────────────────────────────────────────┘

关键要点总结:

  • 文件IO是底层系统调用,无缓存,适合设备文件

  • 目录IO用于目录操作,基于文件IO实现

  • 时间接口用于时间获取和转换,常与文件状态结合使用

  • 三者共同构成Linux系统编程的I/O基础

  • 实际开发中常需结合使用(如遍历目录+获取文件时间)

  • 练习:单词查询(找一个带有单词及其注释的文件,单词和注释在一行)

    赞(0)
    未经允许不得转载:171主机测评 » Linux软件编程:IO编程,文件IO,目录IO,以及一些常用的时间函数接口
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址