Linux系统编程——标准IO

目录

一、Linux文件类型

二、命令行参数

1.命令行参数的核心结构

2.打印命令行参数

三、标准IO库

1.打开文件(fopen)

2.读写文件

1)字符级读写

2)行级读写

3)块级读写

3.关闭文件(fclose)


一、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),系统会自动关闭文件,但仍建议显式调用。
相关推荐
Evan芙2 小时前
DNS服务器类型,解析答案,正反解析域,资源记录定义总结
运维·服务器
wanhengidc2 小时前
巨椰 云手机办公便利性高
运维·服务器·安全·智能手机·云计算
Saniffer_SH3 小时前
【每日一题】PCIe答疑 - 接大量 GPU 时主板不认设备或无法启动和MMIO的可能关系?
运维·服务器·网络·人工智能·驱动开发·fpga开发·硬件工程
爱宇阳3 小时前
Linux 安全加固:禁用 IPv4 ICMP 重定向发送
linux·运维·安全
Saniffer_SH3 小时前
【每日一题】讲讲PCIe链路训练和枚举的前后关系
运维·服务器·网络·数据库·驱动开发·fpga开发·硬件工程
阿豪学编程3 小时前
动静态库制作与原理
linux·个人开发
2401_861786183 小时前
linux修改ip地址(有详细步骤)kali
linux·运维·服务器
颜子鱼3 小时前
Linux platform总线驱动框架
linux·驱动开发
徐子元竟然被占了!!3 小时前
Linux-top
linux·运维·windows