「C语言标准IO全解析:缓冲机制、文件操作与定位技巧」

1. 标准IO:水管系统的「高效输水」

概念:在C库中定义的一组用于输入输出的函数,围绕流进行操作,流用FILE *来描述。

特点

  • 通过缓冲机制减少系统调用,提高效率,就像快递中转站批量处理包裹。

  • 标准IO默认打开了三个流:stdin(标准输入)、stdout(标准输出)、stderr(标准错误)。

缓冲区

  • 全缓冲:与文件相关,缓冲区刷新条件包括程序正常退出、缓冲区溢出、强制刷新fflush、fclose关闭对应的流。

  • 行缓冲:与终端相关,缓冲区刷新条件包括遇到\n、程序正常退出、缓冲区溢出、强制刷新fflush、fclose关闭对应的流。

  • 不缓冲:没有缓冲区,标准错误。

计算缓冲区大小一般为1kb。


2. 函数接口:操作文件的「工具箱」

打开文件fopen

FILE *fopen(const char *path, const char *mode)

功能:打开文件

参数:

  • path:打开的文件路径

  • mode:打开的方式,包括r、r+、w、w+、a、a+ 返回值:成功返回文件流,失败返回NULL

示例

FILE *file = fopen("example.txt", "w");
// 检查文件是否成功打开
if (file == NULL) {
    // 打印错误信息
    perror("Failed to open file");
    return 1;
}
// 文件操作...
// 关闭文件
fclose(file);

// 其他打开模式如 "r"、"a+" 等可根据需要修改,只需将 mode 参数改为对应的模式字符串

关闭文件fclose

int fclose(FILE* stream);

功能:关闭文件 参数:stream:文件流

示例

FILE *file = fopen("example.txt", "w");
// 检查文件是否成功打开
if (file == NULL) {
    // 打印错误信息
    perror("Failed to open file");
    return 1;
}
// 文件操作...
// 关闭文件并检查是否成功
if (fclose(file) != 0) {
    // 打印错误信息
    perror("Failed to close file");
    return 1;
}

读写操作

  • 按照字符串读写:
char * fgets(char *s, int size, FILE * stream);
int fputs(const char *s, FILE * stream);

fgets示例

FILE *file = fopen("example.txt", "r");
// 检查文件是否成功打开
if (file == NULL) {
    // 打印错误信息
    perror("Failed to open file");
    return 1;
}
// 定义缓冲区
char buffer[1024];
// 循环读取文件内容
while (fgets(buffer, sizeof(buffer), file) != NULL) {
    // 打印读取的每一行
    printf("Read line: %s", buffer);
}
// 关闭文件
fclose(file);

// 通过修改 mode 参数为 "w" 或 "a" 等,可以实现不同的写入操作,fputs 的使用方式与上述示例类似,只需将读取操作替换为写入操作即可

  • 按照二进制的方式进行读写:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

fread示例

FILE *file = fopen("example.bin", "rb");
// 检查文件是否成功打开
if (file == NULL) {
    // 打印错误信息
    perror("Failed to open file");
    return 1;
}
// 定义存储数据的数组
int data[5];
// 从文件中读取数据
if (fread(data, sizeof(int), 5, file) != 5) {
    // 打印错误信息
    perror("Failed to read file");
}
// 关闭文件
fclose(file);

// fwrite 的使用方式与 fread 类似,只需将 fopen 的 mode 参数改为 "wb",并将 fread 替换为 fwrite 即可实现写入操作

通过fgets实现"wc -l 文件名"命令功能:计算文件行数。

#include <stdio.h>

int count_lines(const char *filename) {
    // 打开文件
    FILE *file = fopen(filename, "r");
    // 检查文件是否成功打开
    if (file == NULL) {
        // 打印错误信息
        perror("Failed to open file");
        return -1;
    }
    // 定义行数计数器
    int count = 0;
    // 定义缓冲区
    char buffer[1024];
    // 循环读取文件内容
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        // 每读取一行,计数器加1
        count++;
    }
    // 关闭文件
    fclose(file);
    // 返回行数
    return count;
}

int main(int argc, char *argv[]) {
    // 检查命令行参数是否正确
    if (argc != 2) {
        // 打印使用说明
        printf("Usage: %s <filename>\n", argv[0]);
        return 1;
    }
    // 调用函数计算行数
    int lines = count_lines(argv[1]);
    // 检查是否成功计算行数
    if (lines == -1) {
        return 1;
    }
    // 打印行数
    printf("Number of lines: %d\n", lines);
    return 0;
}

3. 文件定位操作:文件中的「导航系统」

void rewind(FILE *stream);
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
  • rewind:将文件位置指针定位到起始位置。

  • fseek:文件的定位操作,参数包括文件流、偏移量和相对位置。

  • ftell:获取当前的文件位置。

注:当打开文件的方式为a或a+时,fseek不起作用。

rewind示例

FILE *file = fopen("example.txt", "r");
// 检查文件是否成功打开
if (file == NULL) {
    // 打印错误信息
    perror("Failed to open file");
    return 1;
}
// 定义缓冲区
char buffer[1024];
// 循环读取文件内容
while (fgets(buffer, sizeof(buffer), file) != NULL) {
    // 打印读取的每一行
    printf("Read line: %s", buffer);
}
// 重置文件位置指针到起始位置
rewind(file);
// 再次循环读取文件内容
while (fgets(buffer, sizeof(buffer), file) != NULL) {
    // 打印读取的每一行
    printf("Read line again: %s", buffer);
}
// 关闭文件
fclose(file);

// fseek 和 ftell 的使用方式与上述示例类似,只需根据需要设置 offset 和 whence 参数即可实现不同的定位操作

避坑指南

  • 缓冲区溢出可能导致数据丢失,注意合理设置缓冲区大小。

  • 文件操作完成后务必关闭文件,避免资源泄漏。

  • 使用fseek时,注意打开文件的方式是否兼容定位操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值