Linux系统编程 - 标准IO

Linux系统编程 - 标准IO

一、标准IO的三个标准流指针

系统为每个程序自动打开三个FILE * 流指针:

流指针 文件描述符 缓存类型 用途
stdin 0 行缓冲 标准输入(键盘)
stdout 1 行缓冲 标准输出(屏幕)
stderr 2 无缓冲 标准错误(屏幕)

特点

  1. 程序启动时自动创建

  2. 不需要fopen(),也不能fclose()

  3. 可直接用于标准IO函数

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

int main() {
    // 使用标准流指针
    fprintf(stdout, "输出到屏幕\n");  // 等同于 printf
    fprintf(stderr, "错误信息\n");    // 立即输出,无缓冲
    fgetc(stdin);                    // 从键盘读取
    return 0;
}

二、标准IO缓存机制

1. 缓存类型对比

缓存类型 大小 刷新条件 适用对象
行缓冲 1024字节 1. 遇到\n 2. 缓冲区满 3. 程序结束 4. fflush() stdinstdout(终端设备)
全缓冲 4096字节 1. 缓冲区满 2. 程序结束 3. fflush() 4. fclose() 普通文件(磁盘文件)
无缓冲 0字节 立即输出 stderr

2. 缓存刷新示例

cpp 复制代码
#include <stdio.h>
#include <unistd.h>

int main() {
    // 行缓冲示例
    printf("Hello");      // 不立即输出(无\n)
    printf(" World");     // 不立即输出
    sleep(2);
    printf("\n");         // 遇到\n,刷新输出
    
    // 全缓冲示例
    FILE *fp = fopen("test.txt", "w");
    for(int i = 0; i < 5000; i++) {
        fputc('A', fp);   // 缓冲区满4096字节时才会写入文件
    }
    fflush(fp);           // 手动刷新缓冲区
    
    // 无缓冲示例
    fprintf(stderr, "立即输出的错误信息\n");
    
    fclose(fp);
    return 0;
}

3. 强制刷新缓存

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

int main() {
    // 刷新标准输出缓存
    printf("正在处理...");
    fflush(stdout);       // 立即输出,不等待\n
    
    // 刷新文件缓存
    FILE *fp = fopen("data.txt", "w");
    fputs("重要数据", fp);
    fflush(fp);           // 立即写入文件,防止数据丢失
    
    // 设置缓存模式
    setvbuf(stdout, NULL, _IONBF, 0);  // 设置为无缓冲
    setvbuf(fp, NULL, _IOFBF, 4096);   // 设置为全缓冲,大小4096
    
    fclose(fp);
    return 0;
}

三、标准IO文件定位

1. 文件定位函数

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

int main() {
    FILE *fp = fopen("test.txt", "r+");
    if(fp == NULL) {
        perror("fopen");
        return -1;
    }
    
    // 1. fseek - 移动文件指针
    fseek(fp, 0, SEEK_SET);     // 移动到文件开头
    fseek(fp, 10, SEEK_CUR);    // 从当前位置向后移动10字节
    fseek(fp, -5, SEEK_END);    // 从文件末尾向前移动5字节
    
    // 2. ftell - 获取当前位置
    long pos = ftell(fp);
    printf("当前位置:%ld字节\n", pos);
    
    // 3. rewind - 重置到文件开头
    rewind(fp);
    printf("重置后位置:%ld字节\n", ftell(fp));
    
    // 示例:计算文件大小
    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    printf("文件大小:%ld字节\n", size);
    rewind(fp);
    
    fclose(fp);
    return 0;
}

2. SEEK_宏定义

复制代码
#define SEEK_SET    0   // 从文件开头
#define SEEK_CUR    1   // 从当前位置
#define SEEK_END    2   // 从文件末尾

四、选择原则

何时使用标准IO?

  1. 处理普通文件,需要缓冲提高性能

  2. 需要格式化输入输出(printf/scanf)

  3. 需要行操作(fgets/fputs)

  4. 跨平台应用

相关推荐
IronMurphy41 分钟前
【算法四十三】279. 完全平方数
算法
墨染天姬1 小时前
【AI】Hermes的GEPA算法
人工智能·算法
wanhengidc1 小时前
云手机 高振畅玩不踩坑
运维·服务器·安全·web安全·智能手机
有谁看见我的剑了?1 小时前
linux 添加硬盘后系统识别不到硬盘处理
linux·运维·服务器
papership1 小时前
【入门级-数据结构-3、特殊树:完全二叉树的数组表示法】
数据结构·算法·链表
smj2302_796826521 小时前
解决leetcode第3911题.移除子数组元素后第k小偶数
数据结构·python·算法·leetcode
JoyCong19981 小时前
ToDesk远程屏幕墙技术白皮书:如何重塑全局运维视界
运维·电脑·远程工作
酿情师2 小时前
yihan:一款面向连续网页学习的智能侧边栏插件
学习·学习方法·工具·学习工具
偶尔上线经常挺尸2 小时前
《100个“反常识”经验15:Nginx 502排查:从应用到内核》
运维·nginx·性能调优·反向代理·502错误·http排错
Beginner x_u2 小时前
链表专题:JS 实现原理与高频算法题总结
javascript·算法·链表