Linux标准IO

一、前置知识:Linux 文件类型与命令行参数

在进行文件操作前,我们需要先了解 Linux 系统中的文件分类,以及如何通过命令行参数灵活传递文件路径等信息。

1.1 Linux 的 7 种文件类型

Linux 是一个 "一切皆文件" 的系统,通过 llls -l 的别名)命令可以查看文件的详细信息,其中第一列的第一个字符代表文件类型,共分为 7 种:

类型标识 文件类型 说明
d 目录文件 用于存放文件和子目录,可通过 cd 命令进入
l 软链接文件 类似 Windows 快捷方式,指向源文件或目录
- 普通文件 包含文本、视频、可执行程序等,如 .c 源码、a.out 可执行文件
c 字符设备文件 按字符流传输数据的设备,如键盘、串口,支持顺序访问
b 块设备文件 按块传输数据的存储设备,如硬盘、U 盘,支持随机访问,块大小通常为 512 字节
s 套接字文件 用于进程间网络通信,常见于 /var/run 目录
p 管道文件 用于进程间的本地通信,实现数据的单向传输

示例:通过 ll 查看文件类型

复制代码
# 目录文件(d)
drwxrwxr-x 10 linux linux 4.0K Sep  6 2021 .vimplus/
# 软链接文件(l)
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
# 字符设备文件(c)
crw------- 1 root root 249, 0 Nov 27 17:06 /dev/rtc0
# 块设备文件(b)
brw-rw---- 1 root disk   8, 0 Nov 27 17:06 /dev/sda

1.2 命令行参数:灵活传递程序参数

在 Linux 程序中,通过 main 函数的参数可以接收命令行传入的数据,格式如下:

复制代码
int main(int argc, char *argv[])
  • argc:命令行参数的总个数,包含程序名本身
  • argv :字符串数组,存储每个命令行参数,argv[0] 为程序名

示例:打印命令行参数

复制代码
#include <stdio.h>

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;
}

编译运行

复制代码
gcc main.c -o arg_demo
./arg_demo file1.txt file2.txt

输出结果

复制代码
argc is 3
0 ./arg_demo
1 file1.txt
2 file2.txt

命令行参数常用于传递文件路径,让程序可以动态操作不同文件。

二、标准 IO 核心基础:默认流指针与缓存机制

标准 IO 的核心特性体现在「默认流指针」和「缓存机制」上,这是理解 IO 操作行为的关键。

2.1 3 个默认流指针:程序的 "标配输入输出"

程序启动时,系统会自动打开 3 个 FILE* 类型的流指针,覆盖基础输入输出场景,无需手动打开 / 关闭:

流指针 说明 常用函数示例
stdin 标准输入(默认键盘) fgets(buf, sizeof(buf), stdin)
stdout 标准输出(默认屏幕) fputs("hello", stdout)
stderr 标准错误输出(默认屏幕) fprintf(stderr, "错误:文件打开失败\n")

核心区别stdout 是「带缓存」输出,stderr 是「无缓存」输出 ------ 错误信息会直接打印到终端,不会因缓存延迟显示。

示例代码:默认流指针使用
复制代码
#include <stdio.h>
#include <string.h>

int main() {
    char input_buf[1024];
    
    // 1. 从stdin(键盘)读取输入
    printf("请输入一句话:"); // printf默认输出到stdout
    fgets(input_buf, sizeof(input_buf), stdin); // 读取键盘输入
    
    // 2. 向stdout(屏幕)输出正常信息
    fputs("你输入的内容是:", stdout);
    fputs(input_buf, stdout);
    
    // 3. 模拟错误,向stderr输出错误信息(无缓存,实时显示)
    if (strlen(input_buf) > 50) {
        fprintf(stderr, "【错误】输入内容超过50个字符,可能存在风险!\n");
    }
    
    return 0;
}

2.2 标准 I/O 的缓存机制:为什么程序 "写了没反应"?

标准 IO 核心是「内存缓存区」:数据先写入内存缓存,满足条件后再批量写入硬件(终端 / 磁盘),以此提升 I/O 效率。缓存分为 3 类,特性如下:

缓存类型 适用场景 缓存大小 刷新(写入硬件)条件
行缓存 stdout(终端交互) 1KB 1. 遇到换行符 \n;2. 缓存区写满;3. 程序结束;4. 主动调用 fflush(stdout)
全缓存 普通文件(如 .txt) 4KB 1. 缓存区写满;2. 程序结束;3. 主动调用 fflush(fp)(fp 为文件流指针)
无缓存 stderr(错误输出) 0(无) 数据直接写入硬件,无延迟
关键问题:"写了没反应" 的常见场景
复制代码
#include <stdio.h>

int main() {
    // 场景1:stdout行缓存------无换行符,数据暂存缓存,终端无输出
    printf("这段文字不会显示"); // 无\n,缓存未刷新
    // fflush(stdout); // 取消注释则手动刷新,终端会显示上述文字
    
    // 场景2:文件全缓存------数据暂存缓存,文件中无内容
    FILE *fp = fopen("test.txt", "w");
    fputs("这段文字暂存缓存", fp); // 缓存未写满,未调用fflush,文件无内容
    // fflush(fp); // 取消注释则手动刷新,文件会写入内容
    fclose(fp); // 关闭文件时会自动刷新全缓存,注释此行则文件无内容
    
    // 场景3:stderr无缓存------直接输出到终端
    fprintf(stderr, "错误信息实时显示\n"); // 无缓存,立即打印
    
    return 0;
}
示例代码:验证缓存机制
复制代码
#include <stdio.h>
#include <unistd.h> // 用于sleep函数

int main() {
    // 1. 验证stdout行缓存:无\n则延迟输出
    printf("stdout行缓存测试(无\\n)"); 
    sleep(3); // 休眠3秒,终端此时无输出
    fflush(stdout); // 手动刷新,终端显示上述文字
    sleep(3); // 再休眠3秒
    printf(" ------ 手动fflush后显示\n"); // 带\n,自动刷新
    
    // 2. 验证文件全缓存
    FILE *fp = fopen("cache_test.txt", "w");
    if (!fp) {
        fprintf(stderr, "文件打开失败!\n");
        return 1;
    }
    // 写入少量数据,缓存未写满,文件暂无内容
    fputs("全缓存测试:未刷新前文件无内容\n", fp);
    printf("此时打开cache_test.txt,文件为空(按回车继续):");
    fgetc(stdin); // 等待用户回车
    
    fflush(fp); // 手动刷新全缓存,数据写入文件
    printf("再次打开cache_test.txt,已能看到内容\n");
    
    // 3. 验证stderr无缓存
    fprintf(stderr, "stderr无缓存:这句话会实时显示,无需等待\n");
    sleep(3); // 休眠3秒,验证无延迟
    
    fclose(fp);
    return 0;
}

三、标准 IO 文件打开模式:读写操作的前提

使用标准 IO 操作文件的第一步是打开文件,通过 fopen 函数实现。打开模式决定了文件的操作权限,读写操作的行为都由其决定,常见模式如下:

模式 操作权限 注意事项
r 只读 目标文件必须存在,写操作会报错
r+ 读写 目标文件必须存在,读写起始位置均为文件开头
w 只写 不存在则创建,存在则清空原有内容,写起始位置为开头
w+ 读写 不存在则创建,存在则清空,读写起始位置均为开头
a 追加写 不存在则创建,写起始位置为文件末尾,不会覆盖原有内容
a+ 追加读写 不存在则创建,写在末尾,读在开头,读新写入内容需调整文件指针

核心函数:fopen

复制代码
FILE *fopen(const char *pathname, const char *mode);
  • pathname:文件的路径(绝对路径或相对路径)+ 文件名
  • mode:文件打开模式
  • 返回值 :成功返回 FILE* 类型的文件流指针(包含文件属性、读写位置等信息);失败返回 NULL

注意 :文件打开后必须通过 fclose 函数关闭,释放系统资源。

四、标准 IO 文件写操作:三种核心方法

标准 IO 提供了多种文件写操作函数,适用于不同场景:单字符写入、字符串写入、二进制数据写入。本文结合代码实例讲解这三种写入方法,覆盖文本文件和二进制文件的写操作场景。

4.1 单字符写入:fputc

fputc 函数用于向文件写入单个字符,适用于逐字符处理的场景(如文本编辑器逐字保存)。

函数原型
复制代码
int fputc(int c, FILE *stream);
  • c:要写入的字符(实际是 ASCII 码值)
  • stream :文件流指针(fopen 的返回值)
  • 返回值 :成功返回写入的字符;失败返回 EOFEOF 是宏定义,值为 -1)
代码实例:逐字符写入文件

需求:通过命令行传递文件路径,向文件写入字符串 "Hello Linux File Write"。

复制代码
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    // 检查命令行参数:必须传入文件路径
    if (argc != 2)
    {
        printf("Usage: %s <filename>\n", argv[0]);
        return -1;
    }

    // 1. 打开文件:追加写模式(a),避免覆盖原有内容
    FILE *fp = fopen(argv[1], "a");
    if (fp == NULL)
    {
        perror("fopen error"); // 打印错误信息
        return -1;
    }

    // 2. 准备写入的字符串
    char *str = "Hello Linux File Write\n";
    int len = strlen(str);

    // 3. 逐字符写入文件
    for (int i = 0; i < len; i++)
    {
        if (fputc(str[i], fp) == EOF)
        {
            perror("fputc error");
            fclose(fp); // 失败时也要关闭文件
            return -1;
        }
    }

    printf("Write success by fputc\n");

    // 4. 关闭文件
    fclose(fp);
    return 0;
}

编译运行

复制代码
gcc fputc_demo.c -o fputc_demo
./fputc_demo test.txt
cat test.txt

输出结果

复制代码
Hello Linux File Write

4.2 字符串写入:fputs

fputc 逐字符写入效率较低,fputs 函数支持一次性写入一个字符串,是文本文件写入的常用方法。

函数原型
复制代码
int fputs(const char *s, FILE *stream);
  • s :要写入的字符串(以 \0 结尾)
  • stream:文件流指针
  • 返回值 :成功返回非负整数;失败返回 EOF
代码实例:字符串写入文件

需求 :向文件写入多行文本,对比 fputc 提升写入效率。

复制代码
#include <stdio.h>

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: %s <filename>\n", argv[0]);
        return -1;
    }

    // 1. 打开文件:只写模式(w),新建或清空文件
    FILE *fp = fopen(argv[1], "w");
    if (fp == NULL)
    {
        perror("fopen error");
        return -1;
    }

    // 2. 多行字符串写入
    char *lines[] = {
        "Linux Standard IO\n",
        "File Write by fputs\n",
        "C Language System Programming\n"
    };
    int line_num = sizeof(lines) / sizeof(lines[0]);

    for (int i = 0; i < line_num; i++)
    {
        if (fputs(lines[i], fp) == EOF)
        {
            perror("fputs error");
            fclose(fp);
            return -1;
        }
    }

    printf("Write success by fputs\n");

    // 3. 关闭文件
    fclose(fp);
    return 0;
}

编译运行

复制代码
gcc fputs_demo.c -o fputs_demo
./fputs_demo test.txt
cat test.txt

输出结果

复制代码
Linux Standard IO
File Write by fputs
C Language System Programming

4.3 二进制写入:fwrite

除了文本文件,标准 IO 还支持二进制文件写入(如图片、视频、可执行程序、结构体数据),核心函数为 fwrite,可实现二进制数据的原生存储,避免文本转换导致的数据丢失。

函数原型
复制代码
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
  • ptr:待写入数据的缓冲区地址(如结构体变量、数组的地址)
  • size:单个数据块的大小(单位:字节)
  • nmemb:数据块的个数
  • stream:文件流指针
  • 返回值 :成功写入的数据块个数(若返回值 < nmemb,说明写入失败或部分失败)
代码实例:结构体数据二进制写入文件

需求 :定义 "学生信息" 结构体,通过 fwrite 将多个学生的二进制数据写入文件,保证数据的原生存储(可通过 fread 无损读取)。

复制代码
#include <stdio.h>
#include <string.h>

// 定义学生信息结构体
typedef struct {
    char name[20];  // 姓名
    int age;        // 年龄
    float score;    // 成绩
} Student;

int main(int argc, char *argv[])
{
    // 检查命令行参数:必须传入二进制文件路径
    if (argc != 2)
    {
        printf("Usage: %s <binary_file>\n", argv[0]);
        return -1;
    }

    // 1. 打开文件:二进制只写模式(wb)
    // 注:Linux下文本/二进制模式无差异,但跨平台(如Windows)需显式加b
    FILE *fp = fopen(argv[1], "wb");
    if (fp == NULL)
    {
        perror("fopen error"); // 打印错误原因(如权限不足、路径不存在)
        return -1;
    }

    // 2. 准备待写入的结构体数据
    Student students[] = {
        {"Zhang San", 18, 92.5},
        {"Li Si", 19, 88.0},
        {"Wang Wu", 17, 95.0}
    };
    int stu_num = sizeof(students) / sizeof(students[0]);

    // 3. 二进制写入结构体数组
    size_t write_num = fwrite(students, sizeof(Student), stu_num, fp);
    if (write_num != stu_num)
    {
        perror("fwrite error");
        fclose(fp);
        return -1;
    }

    printf("Write %zu students data success by fwrite\n", write_num);

    // 4. 关闭文件
    fclose(fp);
    return 0;
}

编译运行

复制代码
gcc fwrite_demo.c -o fwrite_demo
./fwrite_demo student.dat
# 查看二进制文件(可通过hexdump辅助查看)
hexdump -C student.dat

输出结果(核心片段)

复制代码
Write 3 students data success by fwrite
00000000  5a 68 61 6e 67 20 53 61  6e 00 00 00 00 00 00 00  |Zhang San.......|
00000010  00 00 00 00 12 00 00 00  00 00 50 41 4c 69 20 53  |.........PALI S|
00000020  69 00 00 00 00 00 00 00  00 00 00 00 13 00 00 00  |i...............|
00000030  00 00 00 41 57 61 6e 67  20 57 75 00 00 00 00 00  |...AWang Wu.....|
00000040  00 00 00 00 00 11 00 00  00 00 00 c0 41           |.............A|

五、标准 IO 文件读操作:三种核心方法

与写操作对应,标准 IO 同样提供了单字符读取、字符串读取、二进制读取三种核心方法,分别对应 fgetcfgetsfread 函数,覆盖不同的读取场景。

5.1 单字符读取:fgetc

fgetc 函数用于从文件中读取单个字符,适用于逐字符解析的场景(如文本解析器)。

函数原型
复制代码
int fgetc(FILE *stream);
  • stream:文件流指针
  • 返回值 :成功返回读取的字符(ASCII 码值);读到文件末尾或失败返回 EOF
代码实例:逐字符读取文件

需求 :读取 test.txt 文件内容,逐字符输出到终端。

复制代码
#include <stdio.h>

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: %s <filename>\n", argv[0]);
        return -1;
    }

    // 1. 打开文件:只读模式(r)
    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        perror("fopen error");
        return -1;
    }

    // 2. 逐字符读取文件
    int ch;
    printf("File content:\n");
    while ((ch = fgetc(fp)) != EOF)
    {
        putchar(ch); // 输出到终端
    }

    // 3. 检查读取是否正常结束
    if (ferror(fp))
    {
        perror("fgetc error");
        fclose(fp);
        return -1;
    }

    // 4. 关闭文件
    fclose(fp);
    return 0;
}

编译运行

复制代码
gcc fgetc_demo.c -o fgetc_demo
./fgetc_demo test.txt

输出结果

复制代码
File content:
Linux Standard IO
File Write by fputs
C Language System Programming

5.2 字符串读取:fgets

fgetc 逐字符读取效率较低,fgets 函数支持一次性读取一行字符串,是文本文件读取的常用方法,可自动处理换行符。

函数原型
复制代码
char *fgets(char *s, int size, FILE *stream);
  • s:存储读取字符串的缓冲区
  • size :缓冲区大小(读取字符数不超过 size-1,预留 \0 位置)
  • stream:文件流指针
  • 返回值 :成功返回缓冲区地址 s;读到文件末尾或失败返回 NULL
代码实例:按行读取文件

需求 :读取 test.txt 文件,逐行输出并统计行数。

复制代码
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: %s <filename>\n", argv[0]);
        return -1;
    }

    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        perror("fopen error");
        return -1;
    }

    char buf[1024]; // 定义缓冲区
    int line_count = 0;

    printf("File content by line:\n");
    // 逐行读取文件,直到末尾
    while (fgets(buf, sizeof(buf), fp) != NULL)
    {
        line_count++;
        // 去除fgets读取的换行符(可选)
        buf[strcspn(buf, "\n")] = '\0';
        printf("Line %d: %s\n", line_count, buf);
    }

    if (ferror(fp))
    {
        perror("fgets error");
        fclose(fp);
        return -1;
    }

    printf("Total lines: %d\n", line_count);
    fclose(fp);
    return 0;
}

编译运行

复制代码
gcc fgets_demo.c -o fgets_demo
./fgets_demo test.txt

输出结果

复制代码
File content by line:
Line 1: Linux Standard IO
Line 2: File Write by fputs
Line 3: C Language System Programming
Total lines: 3

5.3 二进制读取:fread

fread 函数用于读取二进制文件数据,可无损读取通过 fwrite 写入的结构体、多媒体等二进制数据,是二进制文件操作的核心函数。

函数原型
复制代码
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  • ptr:存储读取数据的缓冲区地址
  • size:单个数据块的大小(单位:字节)
  • nmemb:期望读取的数据块个数
  • stream:文件流指针
  • 返回值 :成功读取的数据块个数;若返回值小于 nmemb,可能是读到文件末尾或出错
代码实例:读取二进制结构体文件

需求 :读取 student.dat 文件中的学生信息,输出到终端。

复制代码
#include <stdio.h>
#include <string.h>

// 与写入时一致的结构体定义
typedef struct {
    char name[20];
    int age;
    float score;
} Student;

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: %s <binary_file>\n", argv[0]);
        return -1;
    }

    // 1. 打开文件:二进制只读模式(rb)
    FILE *fp = fopen(argv[1], "rb");
    if (fp == NULL)
    {
        perror("fopen error");
        return -1;
    }

    Student stu;
    size_t read_num;
    int count = 0;

    printf("Student info:\n");
    printf("Name\t\tAge\tScore\n");
    printf("---------------------------\n");

    // 2. 循环读取结构体数据,直到文件末尾
    while ((read_num = fread(&stu, sizeof(Student), 1, fp)) == 1)
    {
        count++;
        printf("%s\t\t%d\t%.1f\n", stu.name, stu.age, stu.score);
    }

    // 3. 检查读取状态
    if (ferror(fp))
    {
        perror("fread error");
        fclose(fp);
        return -1;
    }

    printf("---------------------------\n");
    printf("Total read %d students\n", count);

    // 4. 关闭文件
    fclose(fp);
    return 0;
}

编译运行

复制代码
gcc fread_demo.c -o fread_demo
./fread_demo student.dat

输出结果

复制代码
Student info:
Name            Age     Score
---------------------------
Zhang San       18      92.5
Li Si           19      88.0
Wang Wu         17      95.0
---------------------------
Total read 3 students

六、文件定位:让指针 "跳着走"

文件流的「读写指针」(类似光标)决定了下一次读写的位置,标准 I/O 提供 3 个函数控制指针位置:

函数 功能 函数原型 核心参数 / 返回值
fseek 移动读写指针 int fseek(FILE *stream, long offset, int whence); offset:偏移字节(正→后移,负→前移);whence:起始位置(SEEK_SET/SEEK_CUR/SEEK_END);返回 0 = 成功,-1 = 失败
ftell 获取当前指针位置 long ftell(FILE *stream); 返回:从文件开头到当前指针的字节数;失败返回 - 1
rewind 指针复位到文件开头 void rewind(FILE *stream); 等价于 fseek(stream, 0, SEEK_SET),无返回值

核心常量说明:

  • SEEK_SET:文件开头(偏移量必须非负);
  • SEEK_CUR:当前指针位置(偏移量可正可负);
  • SEEK_END:文件末尾(偏移量通常为负,向前偏移)。
示例代码:文件定位实战
复制代码
#include <stdio.h>
#include <string.h>

int main() {
    FILE *fp = fopen("position_test.txt", "w+"); // w+:读写模式,创建/清空文件
    if (!fp) {
        fprintf(stderr, "文件打开失败!\n");
        return 1;
    }

    // 1. 写入初始内容
    const char *content = "Hello, File Position!";
    fputs(content, fp);
    printf("写入的内容:%s\n", content);

    // 2. rewind:指针回到文件开头
    rewind(fp);
    printf("rewind后,指针位置:%ld\n", ftell(fp)); // 输出0(文件开头)

    // 3. fseek:移动指针到第6个字节(跳过"Hello,")
    fseek(fp, 6, SEEK_SET); // 从开头偏移6字节(索引从0开始)
    printf("fseek后,指针位置:%ld\n", ftell(fp)); // 输出6

    // 4. 读取指针位置后的内容
    char read_buf[1024];
    fgets(read_buf, sizeof(read_buf), fp);
    printf("从第6字节开始读取:%s\n", read_buf); // 输出" File Position!"

    // 5. fseek:从末尾向前偏移5字节
    fseek(fp, -5, SEEK_END);
    printf("文件末尾向前偏移5字节,指针位置:%ld\n", ftell(fp)); // 输出总长度-5
    fgets(read_buf, sizeof(read_buf), fp);
    printf("从该位置读取:%s\n", read_buf); // 输出"tion!"

    // 6. fseek:从当前位置向后偏移3字节
    fseek(fp, 3, SEEK_CUR);
    printf("当前位置向后偏移3字节,指针位置:%ld\n", ftell(fp));
    // 此时指针超出文件末尾,写入会追加内容
    fputs(" [追加内容]", fp);

    // 7. 验证追加结果:指针回到开头,读取全部内容
    rewind(fp);
    fgets(read_buf, sizeof(read_buf), fp);
    printf("最终文件内容:%s\n", read_buf);

    fclose(fp);
    return 0;
}

七、文件操作的完整流程与注意事项

7.1 标准 IO 文件操作三步曲

  1. 打开文件 :调用 fopen,指定正确的路径和模式,必须检查返回值是否为 NULL,避免空指针操作。
  2. 读写操作 :根据需求选择 fputc/fputs/fwritefgetc/fgets/fread,严格处理函数返回值,判断操作是否成功。
  3. 关闭文件 :调用 fclose 释放资源,即使操作失败也要关闭文件,防止资源泄漏。

7.2 关键注意事项

  1. 模式选择

    • 避免滥用 w 模式:w 会清空文件原有内容,如需追加内容请使用 aa+
    • a+ 模式的读写位置:写在末尾,读在开头,如需读取刚写入的内容,需通过 fseek 函数调整文件指针。
    • 二进制读写需用 rb/wb/ab 模式:跨平台场景下,避免文本模式的换行符转换(如 Windows 下 \n 会转为 \r\n)。
  2. 错误处理

    • 使用 perror 打印错误信息,perror 会自动关联 errno 变量,输出具体错误原因(如文件不存在、权限不足)。
    • 读取操作结束后,可通过 ferror 判断是正常读到文件末尾,还是发生错误。
  3. 缓冲区刷新

    • 标准 IO 默认使用缓冲机制,数据会先存入缓冲区,满足条件后才写入磁盘。
    • 可通过 fflush(fp) 手动刷新缓冲区,确保数据立即写入;关闭文件时 fclose 会自动刷新缓冲区。

八、man 手册:Linux 编程的 "百科全书"

在 Linux 系统编程中,man 手册是查询函数用法的最佳工具,通过指定手册章节可以精准定位信息:

  • man 1 xxx:查询命令的用法(如 man 1 ls
  • man 2 xxx:查询系统调用函数的用法(如 man 2 open
  • man 3 xxx:查询标准库函数的用法(如 man 3 fputc

示例 :查询 fwrite 函数的详细说明

复制代码
man 3 fwrite

导出 man 手册内容

复制代码
man 3 fwrite > fwrite_manual.txt  # 将fwrite的帮助信息保存到文件

九、总结

本文从 Linux 文件类型和命令行参数入手,系统讲解了标准 IO 的核心特性与操作方法,核心逻辑可总结为 "3+3+3" 体系:

核心维度 关键能力
3 个默认流指针 stdin/stdout/stderr 覆盖基础输入输出,stderr 无缓存保证错误实时显示
3 种缓存机制 行缓存(stdout)、全缓存(文件)、无缓存(stderr),平衡效率与实时性
3 类读写方法 字符 / 字符串 / 二进制读写(fputc/fputs/fwrite/fgetc/fgets/fread),适配不同场景
3 个定位函数 fseek(移动指针)、ftell(获取位置)、rewind(复位开头),灵活控制读写位置
操作类型 函数 适用场景 特点
写操作 fputc 逐字符处理文本文件 精细化控制,效率较低
写操作 fputs 批量写入字符串文本 效率高,文本文件首选
写操作 fwrite 二进制数据(结构体、多媒体)写入 原生存储,无数据丢失
读操作 fgetc 逐字符解析文本文件 精细化解析,效率较低
读操作 fgets 按行读取文本文件 效率高,文本文件首选
读操作 fread 二进制数据(结构体、多媒体)读取 无损读取,二进制文件首选
定位操作 fseek 灵活调整读写指针位置 支持多起始位置偏移
定位操作 ftell 获取当前指针位置 便于记录和校验读写位置
定位操作 rewind 快速将指针复位到文件开头 无返回值,使用简单
相关推荐
zl_dfq14 小时前
Linux 之 【简易版的命令行解释器】(getcwd、strtok)
linux
怀旧,14 小时前
【Linux系统编程】10. 进程控制(下)
linux·运维·服务器
Evan芙14 小时前
DNS域名三级结构,DNS服务工作原理,涉及递归和迭代查询原理总结
linux·运维·服务器
石牌桥网管15 小时前
Linux ip 命令教程
linux·运维·tcp/ip
Umi·15 小时前
shell 条件测试
linux·前端·javascript
starvapour15 小时前
替换Ubuntu各种命令的默认编辑器
linux·ubuntu·编辑器
滴答滴答嗒嗒滴15 小时前
Windows无法识别SD卡?SD卡刷这个镜像之后,用读卡器插电脑识别不到了
linux·ubuntu·电脑
qq_4798754315 小时前
深入解析 Protobuf 消息的分帧 (Framing) 与编码 (Codec)
linux·c++
Frank学习路上15 小时前
【Linux】tcpdump抓包工具与wireshark介绍
linux·wireshark·tcpdump