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. 跨平台应用

相关推荐
载数而行5201 天前
QT的五类布局
c++·qt·学习
故事和你911 天前
sdut-程序设计基础Ⅰ-实验五一维数组(8-13)
开发语言·数据结构·c++·算法·蓝桥杯·图论·类和对象
载数而行5201 天前
QT的QString类
c++·qt·学习
像污秽一样1 天前
算法与设计与分析-习题4.2
算法·排序算法·深度优先·dfs·bfs
zl_dfq1 天前
Python学习2 之 【数据类型、运算及相关函数、math库】
学习
va学弟1 天前
Java 网络通信编程(6):视频通话
java·服务器·网络·音视频
Storynone1 天前
【Day20】LeetCode:39. 组合总和,40. 组合总和II,131. 分割回文串
python·算法·leetcode
明明如月学长1 天前
AI 更新太快学不过来?我用OpenClaw打造专属AI学习工作流
算法
幸福指北1 天前
我用 Tauri + Vue 3 + Rust 开发了这款跨平台网络连接查看工具PortView,性能炸裂!
运维·网络·监控
黎阳之光1 天前
【黎阳之光:以无线专网与视频孪生,赋能智慧广电与数字中国】
算法·安全·智慧城市·数字孪生