当前位置: 首页 > news >正文

Linux 文件与目录操作详解

目录

简介

基本概念

1. 常见文件类型操作接口:

系统库(简单跨平台)

C 标准库(高性能底层调用)

2. 文件与目录操作核心函数

标准库 FILE*

系统调用

目录操作

项目实战一:实现 wc 功能

功能示例

关键点

 代码实现

项目实战二:文件分卷与哈希摘要

示例

使用接口

openssl 安装 

代码实现

总结


简介

在 Linux 系统中,一切皆文件。本文从 Linux 文件的基本操作函数讲起,结合三个实际任务案例,带你全面掌握文件读写、目录遍历、文件切片、哈希摘要等常用操作。无论你是系统程序员、服务器开发者,还是操作系统课程的学习者,本篇内容都能帮你打好底层基础。

基本概念

Linux 把所有内容抽象为文件,统一进行读写操作:

  • 普通文件与文件夹

  • 设备文件(如 /dev/null

  • 网络套接字

  • 进程信息(如 /proc/self

文件的抽象来源于“流”的概念 —— 一串从源头流向目的地的字节序列。

1. 常见文件类型操作接口:

系统库(简单跨平台)

    - `open`

    - `close`

    - `read`

    - `write`

    - `ioctrl`

C 标准库(高性能底层调用)

    - `fopen`

    - `fclose`

    - `fread`

    - `fwrite`

    - `fseek`

    - `fgetc`

    - `fputc`

    - `fgets`

    - `fputs`

2. 文件与目录操作核心函数

标准库 FILE*

适用于文本文件和缓冲处理:

FILE *fp = fopen("a.txt", "r");    // 打开一个用于读取的文件。该文件必须存在。
fgetc(fp);    // 读取单个字符
fgets(buf, n, fp);  // 读取一行
fclose(fp);    // 关闭文件

mode

- r     只读

- r+    读写

- w     只写,截断

- w+    读写,截断

- a     追加

- a+    追加读

- b     二进制格式

系统调用

适合大文件和高并发场景:

int fd = open("a.txt", O_RDONLY);
read(fd, buf, n);
lseek(fd, offset, SEEK_SET);
close(fd);
目录操作

需引入头文件 <dirent.h><sys/stat.h>

DIR *dp = opendir(".");
struct dirent *entry;
while ((entry = readdir(dp)) != NULL) {printf("%s\n", entry->d_name);
}
closedir(dp);

项目实战一:实现 wc 功能

目标:实现命令 wc 的常用功能(字节数、词数、行数)

功能示例

./wc -c a.txt   # 字节数
./wc -w a.txt   # 单词数
./wc -l a.txt   # 行数
./wc a.txt      # 全部统计

关键点

  • fgetc() 逐字符读取

  • 判断空格、换行、制表符统计词数

  • 行数遇 '\n' 增加

  • 使用 fseek + ftell 获取文件大小(字节数)

 代码实现

// 简单实现 wc 的功能
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void count_file(const char *filename, int count_line, int count_word, int count_byte);int main(int argc, char const *argv[])
{if (argc < 2){printf("用法: %s [-c] [-w] [-l] 文件名\n", argv[0]);return EXIT_FAILURE;}int count_line = 0;int count_word = 0;int count_byte = 0;const char *filename = NULL;for (int i = 1; i < argc; i++){if (strcmp(argv[i], "-l") == 0){count_line = 1;}else if (strcmp(argv[i], "-w") == 0){count_word = 1;}else if (strcmp(argv[i], "-c") == 0){count_byte = 1;}else{filename = argv[i];}}if (!filename){fprintf(stderr, "未指定文件名\n");return EXIT_FAILURE;}count_file(filename, count_line, count_word, count_byte);return EXIT_SUCCESS;
}void count_file(const char *filename, int count_line, int count_word, int count_byte)
{FILE *fp = fopen(filename, "r");if (!fp){perror("文件打开失败");return;}int lines = 0;int words = 0;int bytes = 0;int in_word = 0;int c;while ((c = fgetc(fp)) != EOF){bytes++;if (c == '\n') lines++;if (c == ' ' || c == '\n' || c == '\t'){in_word = 0;}else if (!in_word){in_word = 1;words++;}}fclose(fp);if (!count_line && !count_word && !count_byte){count_line = count_word = count_byte = 1;}if (count_line) printf("行数: %d\n", lines);if (count_word) printf("单词数: %d\n", words);if (count_byte) printf("字节数: %d\n", bytes);
}

项目实战二:文件分卷与哈希摘要

目标:将大文件按固定大小切分,并对每一部分计算 SHA256 哈希

示例

./split a.txt 512
# 输出文件:
#   a.txt.001
#   a.txt.002
#   ...
#   m.txt      # 各分卷哈希值 + 全文件哈希

使用接口

  • open, read, write 实现二进制读取与写入

  • openssl/sha.h + SHA256() 计算哈希

  • 文件命名使用 snprintf 构造 a.txt.001

openssl 安装 

sudo apt install libssl-dev

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <openssl/sha.h>
#include <sys/stat.h>void sha256_hash(const unsigned char *data, size_t len, char *out_hex) {unsigned char hash[SHA256_DIGEST_LENGTH];SHA256(data, len, hash);for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {sprintf(out_hex + i * 2, "%02x", hash[i]);}
}int main(int argc, char *argv[]) {if (argc != 3) {printf("用法: %s 文件名 分卷大小(字节)\n", argv[0]);return 1;}const char *filename = argv[1];int chunk_size = atoi(argv[2]);int fd = open(filename, O_RDONLY);if (fd < 0) {perror("open");return 1;}unsigned char *buffer = malloc(chunk_size);if (!buffer) {perror("malloc");close(fd);return 1;}FILE *meta_fp = fopen("m.txt", "w");if (!meta_fp) {perror("fopen m.txt");free(buffer);close(fd);return 1;}int chunk_num = 1;ssize_t read_bytes;SHA256_CTX full_ctx;SHA256_Init(&full_ctx);while ((read_bytes = read(fd, buffer, chunk_size)) > 0) {char sha_hex[65] = {0};sha256_hash(buffer, read_bytes, sha_hex);// 写入分卷char part_filename[256];snprintf(part_filename, sizeof(part_filename), "%s.%03d", filename, chunk_num++);FILE *part_fp = fopen(part_filename, "wb");fwrite(buffer, 1, read_bytes, part_fp);fclose(part_fp);fprintf(meta_fp, "%s\n", sha_hex);SHA256_Update(&full_ctx, buffer, read_bytes);}// 计算整个文件的 SHA256unsigned char full_hash[SHA256_DIGEST_LENGTH];SHA256_Final(full_hash, &full_ctx);char final_sha[65] = {0};for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {sprintf(final_sha + i * 2, "%02x", full_hash[i]);}fprintf(meta_fp, "%s\n", final_sha);  // 写入最后一行printf("完整文件 SHA256: %s\n", final_sha);fclose(meta_fp);close(fd);free(buffer);return 0;
}

总结

本文从文件操作的基本概念出发,结合 wc 命令实现与文件分卷哈希两个实战案例,全面介绍了 Linux 下文件与目录的读写方法及系统调用的实际应用。通过这些练习,读者不仅能掌握文本与二进制文件的处理技巧,还能理解哈希摘要在数据完整性校验中的重要作用,为后续深入系统编程与工具开发打下坚实基础。

http://www.lryc.cn/news/608889.html

相关文章:

  • 从Docker衔接到导入黑马商城以及前端登录显示用户或密码错误的相关总结(个人理解,仅供参考)
  • PyTorch生成式人工智能(24)——使用PyTorch构建Transformer模型
  • accept4系统调用及示例
  • ABP VNext + CloudEvents:事件驱动微服务互操作性
  • 数据治理:DQC(Data Quality Center,数据质量中心)概述
  • [每周一更]-(第153期):**PDF终极防护指南:命令行全栈加密+一键权限锁死实战(附脚本模板)**
  • Docker--解决x509: certificate signed by unknown authority
  • 医院课题管理全动态流程 (AI-Enhanced, Data-Driven Research Lifecycle)
  • JAVA中的String类方法介绍
  • 基于transformer的目标检测——匈牙利匹配算法
  • 【Excel】利用函数和Power Query进行数据分析
  • 基于Matlab的深度学习智能行人检测与统计系统
  • Java企业级应用性能优化实战
  • 2025年人工智能十大趋势 - 基础模型的跃迁
  • 达梦数据库联机备份和脱机备份的区别
  • C++ 入门基础(3)
  • 自私挖矿攻击
  • C++引用:高效安全的别名机制详解
  • RPG增容3:尝试使用MVC结构搭建玩家升级UI(一)
  • Claude Code入门学习笔记(四)--Claude Code的使用
  • [硬件电路-150]:数字电路 - 数字电路与模拟电路的异同
  • 志邦家居PMO负责人李蓉蓉受邀为PMO大会主持人
  • Rust:开发 DLL 动态链接库时如何处理 C 字符串
  • 2025-0803学习记录21——地表分类产品的精度验证
  • 多向量检索:lanchain,dashvector,milvus,vestorsearch,MUVERA
  • gemini-cli +llms
  • 嵌入式硬件篇---Openmv
  • 问题集000
  • 对接古老系统的架构实践:封装混乱,走向有序
  • ⭐CVPR2025 FreeUV:无真值 3D 人脸纹理重建框架