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

关于linux操作系统下的文件操作方法:

以下是对笔记中 Linux 文件操作(标准 I/O 为主) 知识点的系统总结,包含核心概念梳理、补充细节,并以表格整理标准 I/O 函数的参数与功能:


一、Linux 应用开发核心方向

笔记围绕 Linux 下的软件开发 展开,核心方向包括:

方向说明关联知识点
文件操作对 Linux 各类文件(块设备、字符设备等)进行读写控制文件类型、标准 I/O/文件 I/O 函数
多任务通过进程、线程实现程序并行/并发执行进程创建(fork)、线程管理等
网络编程实现网络数据传输、通信Socket 编程、TCP/UDP 协议等
网络服务器构建开发支持网络请求的服务程序HTTP 协议、套接字监听/响应逻辑
数据库数据持久化存储与管理MySQL、SQLite 等数据库操作

二、Linux 文件类型(7 种)

Linux 中“一切皆文件”,通过 ls -l 可查看文件类型(首字符标识 ):

文件类型首字符类型说明典型应用场景示例/备注
b块设备文件存储设备(硬盘、U盘 )/dev/sda(硬盘分区 )
c字符设备文件输入输出设备(键盘、显示器 )/dev/tty(终端 )、/dev/usb
d目录文件存储文件/子目录的“容器”任意文件夹(如 /home
-普通文件存储文本、二进制、图片等数据.c 源码、.txt 文档、可执行文件
l软链接文件(符号链接 )快捷方式,指向其他文件/目录的路径ln -s 原文件 软链接名 创建
s套接字文件进程间网络通信(本地/网络套接字 )/var/run/mysqld/mysqld.sock
p管道文件进程间通信(匿名/命名管道 )mkfifo 管道名 创建

三、文件操作核心流程

无论标准 I/O 还是文件 I/O,均遵循 “打开 → 读写 → 关闭” 三步:

步骤说明标准 I/O 关键函数文件 I/O 关键函数(补充)
打开关联文件与程序,获取操作句柄fopen(返回 FILE* 流指针 )open(返回文件描述符 fd
读写按字符、行、数据块读写内容fgetc/fputcfgets/fputsread/write(按字节流读写 )
关闭释放资源,确保数据落盘fcloseclose(关闭文件描述符 )

Linux fopen 函数打开模式(mode)说明表格,包含每种模式的含义、文件存在/不存在时的行为:

模式含义说明文件存在时的行为文件不存在时的行为典型应用场景
r只读(read only)打开文件,流指针指向文件开头报错(返回 NULL读取配置文件、日志文件等
r+读写(read + write)打开文件,流指针指向文件开头报错(返回 NULL读取并修改现有文件内容
w只写(write only,清空文件)清空文件内容,流指针指向开头创建新文件覆盖写入全新内容(如日志重置)
w+读写(write + read,清空文件)清空文件内容,流指针指向开头创建新文件覆盖写入并需要读取的场景
a追加写(append only)流指针移到文件末尾(保留内容)创建新文件日志追加、消息队列写入
a+追加读写(append + read)读:指针在开头;写:指针在末尾创建新文件追加内容同时需要回读的场景

补充说明

  1. 模式区分细节

    • r/r+ 严格依赖文件已存在,否则直接失败(返回 NULL,需检查 errno 确认错误 )。
    • w/w+强制清空现有文件(即使文件有内容 ),适合“覆盖写入”场景。
    • a/a+写操作始终在文件末尾(无论指针如何移动 ),但读操作可自由调整指针位置(如 fseek )。
  2. 实践建议

    • 打开文件后务必检查返回值(if (fp == NULL) { perror("fopen"); exit(1); } )。
    • 不同模式的指针行为需注意,尤其是 a+ 模式(读和写的指针位置独立 )。
  3. 跨平台差异
    Windows 系统下,fopen 模式需额外区分文本模式("rt"/"wt" )和二进制模式("rb"/"wb" ),但 Linux 下无此严格区分(默认二进制模式 )。

通过表格可直观对比各模式的行为差异,开发时根据需求(读、写、追加、覆盖 )选择对应模式即可。

四、标准 I/O 函数总结(核心函数参数 & 功能表)

标准 I/O 由 C 标准库(stdio.h)提供,基于 文件流(FILE* 操作,核心函数如下:

1. 文件打开:fopen
FILE *fopen(const char *pathname, const char *mode);  
要素说明
功能打开文件并返回 文件流指针FILE*),失败返回 NULL
参数- pathname:文件路径(如 "/tmp/test.txt"
- mode:打开模式(见下表)
返回值成功返回 FILE* 流指针,失败返回 NULL(需检查 errno 定位错误)。
需要检查返回值以判断文件是否成功打开:
FILE *fp=fopen("./1.txt","w+");FILE *fp1=fp;if(fp==NULL){printf("fopen error\n");return -1;}
2. 文件关闭:fclose
int fclose(FILE *stream);  
要素说明
功能关闭文件流,刷新缓冲区,释放资源。
参数streamfopen 返回的文件流指针(FILE*)。
返回值成功返回 0,失败返回 EOF(需检查 ferror(stream) 确认错误)。
对文件执行fopen后别忘了执行fclose关闭打开的文件:
3. 字符读写:fgetc / fputc
  • 读字符:fgetc
    int fgetc(FILE *stream);  
    
要素说明
功能从文件流 stream 读取一个字符(ASCII 码),流指针后移 1 字节。
参数stream:文件流指针(FILE*)。
返回值成功返回字符的 ASCII 码(int 类型,如 'A' 对应 65);失败/到文件末尾返回 EOF
代码:
#include<stdio.h>
int main(void)
{FILE *fp=fopen("./1.txt","w+");FILE *fp1=fp;if(fp==NULL){printf("fopen error\n");return -1;}fputc('h',fp);fputc('e',fp);fputc('l',fp);fputc('l',fp);fputc('o',fp);fputc(' ',fp);fputc('w',fp);fputc('o',fp);fputc('r',fp);fputc('l',fp);fputc('d',fp);int ret=fgetc(fp1);
/*	if(ret==EOF){printf("end of file or error\n");}*/while(ret!=EOF){printf("%c",ret);ret=fgetc(fp1);}fclose(fp);printf("fopen successful\n");return 0;
}
  • 写字符:fputc
    int fputc(int c, FILE *stream);  
    
要素说明
功能向文件流 stream 写入一个字符c 的 ASCII 码),流指针后移 1 字节。
参数- c:要写入的字符(如 'A' 或直接传 ASCII 码 65
- stream:文件流指针
返回值成功返回写入字符的 ASCII 码;失败返回 EOF
代码:逐个字符读取:
#include<stdio.h>
int main(void)
{FILE *fp=fopen("1.txt","r");int ret=fgetc(fp);
/*	if(ret==EOF){printf("end of file or error\n");}*/while(ret!=EOF){printf("%c",ret);ret=fgetc(fp);}fclose(fp);printf("fopen successful\n");return 0;
}
4. 行读写:fgets / fputs
  • 读一行:fgets
    char *fgets(char *s, int size, FILE *stream);  
    
要素说明
功能从文件流 stream 读取一行数据(最多读 size-1 个字符,遇 \n 或文件末尾停止 ),自动在 s 末尾加 \0
参数- s:存储数据的缓冲区(字符数组,如 char buf[1024]
- size:缓冲区大小(需 >1,预留 \0 空间 )
- stream:文件流指针
返回值成功返回 s 缓冲区地址;失败/到文件末尾返回 NULL
代码:
#include<stdio.h>
int main(int argc, const char *argv[])
{FILE *PGS=fopen("./4.txt","r");if(PGS==NULL){printf("fopen error\n");return -1;}char s[100]={0};while(1){char *p=fgets(s,sizeof(s),PGS);if(p==NULL){break;}printf("%s\n",p);}fclose(PGS);return 0;
}
  • 写一行:fputs
    int fputs(const char *s, FILE *stream);  
    
要素说明
功能向文件流 stream 写入字符串s 内容,不自动加 \n,需手动添加 )。
参数- s:要写入的字符串(以 \0 结尾,如 "hello"
- stream:文件流指针
返回值成功返回非负整数(通常是写入字符数 );失败返回 EOF
代码:
#include<stdio.h>
int main(int argc , const char *argv[])
{FILE *FP=fopen("./4.txt","w");if(FP==NULL){printf("fopen error\n");return -1;}char s[100]={"china!\n"};int ret=fputs(s,FP);if(ret==EOF){printf("fputs error!\n");return -1;}return 0;
}
5. 数据块读写:fread / fwrite(补充)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);  
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);  
要素说明
功能数据块读写文件(适合二进制文件,如结构体、图片 )。
参数- ptr:缓冲区地址(读时存数据,写时取数据 )
- size:单个数据块大小(字节 )
- nmemb:数据块数量
- stream:文件流指针
返回值实际读写的数据块数量size_t );失败或到末尾可能小于 nmemb

五、补充细节 & 易错点

  1. 文件流指针移动
    读写操作会改变流指针位置(如 fgetc 后指针后移 1 字符 ),同一程序中“写后直接读”需用 fseek 重置指针(如 fseek(stream, 0, SEEK_SET) 回到文件开头 )。

  2. 缓冲区机制
    标准 I/O 带用户态缓冲区,数据先写入缓冲区,再由系统决定何时刷入磁盘。需立即落盘时,调用 fflush(stream) 手动刷新。

  3. 命令行参数:argc / argv
    主函数参数用于接收命令行输入:

    int main(int argc, char *argv[]);  
    
    • argc:参数总个数(含程序名 )。
    • argv:参数数组,argv[0] 是程序路径/名称,argv[1] 开始是用户输入参数。

六,主函数传参的使用方法

以下是结合笔记内容,对 Linux C 主函数传参(argc/argv 的总结与补充,用清晰的逻辑和示例说明用法:


1、主函数传参基础概念

在 Linux C 程序中,主函数 main 支持通过命令行传递参数,形式为:

int main(int argc, char *argv[]);  
参数名含义
argc参数个数(argument count):包含程序名在内的所有命令行参数总数。
argv参数数组(argument vector):字符串数组,存储每个命令行参数的内容。
2、传参规则与示例

以笔记中示例 ./a.out aaa bbb 为例:

命令行输入argcargv 数组内容说明
./a.out aaa bbb3argv[0] = "./a.out"
argv[1] = "aaa"
argv[2] = "bbb"
- argv[0] 固定为程序名/路径
- argv[1] 开始是用户传入的参数
3、传参方法与场景
1. 基础用法:命令行直接传参

编译生成可执行文件(如 a.out )后,在终端通过以下方式传参:

./a.out 参数1 参数2 参数3 ...  
  • 示例代码(遍历参数):
    #include <stdio.h>  int main(int argc, char *argv[]) {  printf("参数总数 argc = %d\n", argc);  for (int i = 0; i < argc; i++) {  printf("argv[%d] = %s\n", i, argv[i]);  }  return 0;  
    }  
    
  • 运行输出(输入 ./a.out aaa bbb ):
    参数总数 argc = 3  
    argv[0] = ./a.out  
    argv[1] = aaa  
    argv[2] = bbb  
    
4、关键细节补充
  1. argv 数组的结束标志
    argv[argc] 固定为 NULL,可用于遍历参数时的终止判断:

    for (int i = 0; argv[i] != NULL; i++) {  printf("argv[%d] = %s\n", i, argv[i]);  
    }  
    
  2. 参数的本质是字符串
    argv 存储的是字符串,如需数值运算(如 ./app 10 20 ),需用 atoi/atof 转换:

    #include <stdlib.h>  
    int num1 = atoi(argv[1]); // "10" → 10  
    int num2 = atoi(argv[2]); // "20" → 20  
    
  3. 空格与引号处理

    • 命令行参数以空格分隔,如需传递含空格的参数,用引号包裹:
      ./app "hello world"  # argv[1] = "hello world"(含空格)  
      
    • 特殊字符(如 $* )需用反斜杠转义(\)或引号包裹。

七、总结表格(标准 I/O 核心函数参数速查表)

函数函数原型核心参数说明典型用途
fopenFILE *fopen(const char *pathname, const char *mode);pathname(路径)、mode(打开模式)打开文件并获取流指针
fcloseint fclose(FILE *stream);stream(文件流指针)关闭文件、刷新缓冲区
fgetcint fgetc(FILE *stream);stream(文件流指针)读 1 个字符
fputcint fputc(int c, FILE *stream);c(字符)、stream(文件流指针)写 1 个字符
fgetschar *fgets(char *s, int size, FILE *stream);s(缓冲区)、size(最大读入字符 )、stream(文件流指针)读 1 行数据
fputsint fputs(const char *s, FILE *stream);s(字符串)、stream(文件流指针)写 1 行字符串(不含 \0

使用fopen ,fputc,fgetc,fclose实现拷贝的功能:

代码:

#include<stdio.h>
int main(int argc ,const char *argv[])
{if(argc!=3){printf("Usage : ./a.out <srcfile> <dstfile>\n");return -1;}FILE *fp=fopen(argv[1],"r");if(fp==NULL){printf("fopen error\n");return -1;}FILE *fcp=fopen(argv[2],"w");if(fcp==NULL){printf("fopen error\n");return -1;}int ret =fgetc(fp);if(ret==EOF) {printf("end of file or error");}while(ret!=EOF){fputc(ret,fcp);ret=fgetc(fp);}fclose(fp);fclose(fcp);return 0;
}

使用fopen,fgets,fputs,fclose库函数实现字符串的拷贝:

代码

#include<stdio.h>
int main(int argc,const char *argv[])
{if(argc!=3){printf("Usage : copy  <srcfile> <dstfile>\n");return -1;}FILE *FGT=fopen(argv[1],"r");if(FGT==NULL){printf("fopen error\n");return -1;}FILE *FPT=fopen(argv[2],"w");if(FPT==NULL){printf("fopen error\n");return -1;}char s[100]={0};while(1){char *fgt=fgets(s,sizeof(s),FGT);if(fgt==NULL){break;}int fpt=fputs(fgt,FPT);if(fpt==EOF){printf("fputs error\n");return -1;}}fclose(FGT);fclose(FPT);return 0;
}
http://www.dtcms.com/a/325100.html

相关文章:

  • 深度解析1688关键字搜索API接口:技术实现与应用探索
  • 【Nginx知识】nginx日志配置详解
  • 使用线性降维方法进行数据降维
  • token危机解决?扩散模型数据潜力3倍于自回归,重训480次性能仍攀升
  • Java历代JDK核心特性演进(JDK9-21精华版)
  • 【Docker实战入门】从核心概念到镜像构建
  • 微服务架构中过滤器(Filter)与拦截器(Interceptor)的区别
  • 线程池111
  • Spring Boot - 内置的9个过滤器用法
  • 串联所有单词的子串
  • 【力扣198】打家劫舍
  • Windows选择文件自动删除及输入框自动打字的解决办法
  • 当varchar和Nvarchar关联
  • 6A 工作流:让 Cursor、Trae 等AI编程助手按流程交付的实战手册
  • Java 基础编程案例:从输入交互到逻辑处理
  • 基于django的宠物用品购物商城的设计与实现
  • [创业之路-540]:经营分析会 - 如何实现销售0到1营收的突破
  • 从DDPM对比学习Diffusion Policy:生成模型到策略学习的演进
  • Spring Boot 开发三板斧:POM 依赖、注解与配置管理
  • 字节:计算机存储单位
  • 计算机视觉实战:用YOLO打造智能停车场空位雷达
  • 线程互斥与锁机制详解
  • 【模板】拓扑排序
  • 性能解析案例
  • 人工智能与体育:体育产业的革新
  • Vue3从入门到精通: 2.5 Vue3组件库开发与设计系统构建
  • Python day40
  • Leetcode 3645. Maximum Total from Optimal Activation Order
  • vulnhub-drippingblues靶场攻略
  • VTA学习笔记