目录
一、Linux文件类型
Linux 系统中一切皆文件,但不同文件有着不同的属性和用途。通过 ll(ls -l的别名)命令查看文件时,输出结果第一列的第一个字符就代表了文件类型,共 7 种核心类型,具体如下:
| 类型标识 | 文件类型 | 特点与应用场景 |
|---|---|---|
| d | 目录文件 | 用于存储文件和子目录,可通过cd命令进入,类似 Windows 的文件夹 |
| l | 软链接文件 | 相当于 Windows 的快捷方式,指向源文件 / 目录,删除链接不影响源文件 |
| - | 普通文件 | 存储实际数据,如代码文件(1.c)、可执行文件(a.out)、文档、视频等 |
| c | 字符设备文件 | 按字符流传输数据的设备,如键盘、鼠标、串口,数据传输有序且体积小,大部分设备属于此类 |
| b | 块设备文件 | 存储设备(硬盘、U 盘、光盘),按 512 字节 / 块传输,支持随机访问 |
| s | 套接字文件 | 用于进程间网络通信(TCP/UDP),常见于/tmp或服务程序的通信目录 |
| p | 管道文件 | 用于同一主机上的进程间通信(IPC),数据传输后自动清空,不持久化存储 |
示例:
drwxrwxr-x 10 linux linux 4.0K Sep 6 2021 .vimplus/(目录文件)
lrwxrwxrwx 1 linux linux 27 Sep 5 2021 .vimrc -> /home/linux/.vimplus/.vimrc(软链接文件)
-rw-rw-r-- 1 linux linux 3.4K Sep 22 11:28 .vimrc.custom.config(普通文件)
man 手册的核心查询规则:
man(manual)手册是 Linux 系统中最权威的帮助工具,可查询命令、函数、配置文件等所有系统相关内容。掌握其查询规则,能快速获取函数参数、返回值、使用示例等关键信息。
| 命令格式 | 功能说明 |
|---|---|
| man man | 查看 man 手册自身的帮助信息(含所有章节介绍) |
| man man > 文件名 | 将 man 手册的帮助信息保存到文件 |
| man xxx | 默认查询 xxx 的帮助(优先匹配最小章节号) |
| man 1 xxx | 查看 xxx命令的帮助(第 1 章节) |
| man 2 xxx | 查看 xxx系统调用函数的帮助(第 2 章节) |
| man 3 xxx | 查看 xxx标准库函数的帮助(第 3 章节) |
二、命令行参数
1.命令行参数的核心结构
C 语言程序的 main 函数支持两个参数,用于接收命令行输入:
int main(int argc, char *argv[ ])
- **argc:**argument count,命令行参数的总个数(包含程序名本身)。例如执行./a.out 1 2 3时,argc=4。
- **argv:**argument vector,字符串数组,存储每个命令行参数的内容。argv[0]是程序名(如./a.out),argv[1]是第一个参数(如1),以此类推,最后一个元素argv[argc]为NULL。
2.打印命令行参数
下面的代码可遍历并打印所有命令行参数,帮助理解参数传递逻辑:
cpp
int main(int argc, char *argv[])
{
printf("argc is %d\n", argc);
int i = 0 ;
for(i = 0 ; i < argc; i++)
{
printf("%d %s\n", i, argv[i]);
}
return 0;
}
三、标准IO库
1.打开文件(fopen)
函数原型:
FILE *fopen(const char *pathname, const char *mode);
- **pathname:**文件路径(绝对路径如/home/linux/test.txt,相对路径如test.txt)
- **mode:**打开模式,决定文件的读写权限和初始位置,核心模式如下表:
| 打开模式 | 权限说明 | 注意事项 |
|---|---|---|
| r | 只读,读写位置从文件开头开始 | 目标文件必须存在 |
| r+ | 读写,读写位置从文件开头开始 | 目标文件必须存在 |
| w | 只写,读写位置从文件开头开始 | 会创建文件,并清空文件 |
| w+ | 读写,读写位置从文件开头开始 | 会创建文件,并清空文件 |
| a | 追加写,读写位置从文件末尾开始 | 会创建文件 |
| a+ | 追加写 + 读,写位置从文件末尾开始,读位置从文件开头开始 | 会创建文件 |
2.读写文件
1)字符级读写
**适用场景:**逐个字符处理文件(如文本文件的字符统计)。
| 函数 | 说明 | 原型 |
| fgetc | 从文件读取一个字符,到达结尾返回EOF | int fgetc(FILE *stream); |
| fputc | 向文件写入一个字符,写入错误返回EOF | int fputc(int c, FILE *stream); |
|---|
- **c:**要写入的字符(虽然是int类型,但实际只取低 8 位)
- **stream:**是文件流指针(如fp)
**示例:**用 fputc 和 fgetc 复制文件
cpp
int main()
{
// 打开源文件(只读)和目标文件(只写,不存在则创建)
FILE *src_fp = fopen("source.txt", "r");
FILE *dest_fp = fopen("dest.txt", "w");
if (src_fp == NULL || dest_fp == NULL)
{
printf("fopen failed\n");
return 1;
}
int ch; // 必须用int接收fgetc返回值,避免EOF(-1)与字符(0-255)混淆
// 循环读取源文件字符,直到EOF
while ((ch = fgetc(src_fp)) != EOF)
{
fputc(ch, dest_fp); // 将读取的字符写入目标文件
}
printf("File copied successfully!\n");
// 关闭文件(先关目标文件,再关源文件,避免资源泄漏)
fclose(dest_fp);
fclose(src_fp);
return 0;
}
2)行级读写
**适用场景:**按行处理文件(如读取配置文件、日志文件)。
| 函数 | 说明 | 原型 |
| fgets | 从文件读取一行字符,到达结尾返回NULL | char *fgets(char *s, int size, FILE *stream); |
| fputs | 向文件写入一个字符串 | int fputs(const char *s, FILE *stream); |
|---|
- **s:**要写入的字符串(需以\0结尾)
- **size:**数组大小(建议比预期行长大 2,预留\n和\0)
- **stream:**文件流指针
**示例:**用 fgets 和 fputs 读取并打印文件内容
cpp
int main()
{
FILE *fp = fopen("test.txt", "r");
if (fp == NULL)
{
printf("fopen failed\n");
return 1;
}
char buf[100]; // 定义缓冲区数组
// 循环读取每一行,直到EOF
while (fgets(buf, sizeof(buf), fp) != NULL)
{
fputs(buf, fp);
}
fclose(fp);
return 0;
}
3)块级读写
**适用场景:**二进制文件(如图片、音频、可执行文件)或批量数据(如结构体数组)的读写,效率最高。
| 函数 | 说明 | 原型 |
| fwrite | 向文件写入指定数量的块数据 | size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); |
| fread | 从文件读取指定数量的块数据 | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); |
|---|
- **ptr:**数据的首地址
- **size:**每个块的字节数
- **nmemb:**块的个数
- **stream:**文件流指针
3.关闭文件(fclose)
文件操作完成后,必须调用 fclose 关闭文件,否则会导致:
- 缓冲区数据未刷新(部分数据未写入磁盘)
- 系统资源泄漏(每个进程可打开的文件数有限)
函数原型:
int fclose(FILE *stream);
- **stream:**要关闭的文件流指针
注意事项:
- 关闭文件后,不可再通过该文件流指针操作文件;
- 建议先关闭写入流(如dest_fp),再关闭读取流(如src_fp),避免数据丢失;
- 若程序异常退出(如未调用fclose),系统会自动关闭文件,但仍建议显式调用。