22. 课件整理 文件IO
























标准IO操作总结
本文档围绕标准IO操作展开,详细介绍了字符输入输出、行输入输出以及二进制读写的相关函数、返回值、功能特点和注意事项,具体内容如下:
一、字符输入(读单个字符)
(一)相关函数
| 函数/宏 | 格式 | 功能说明 |
|---|---|---|
| fgetc(函数) | int fgetc(FILE *stream) | 从指定流stream中读取单个字符 |
| getc(宏) | int getc(FILE *stream) | 作用与fgetc类似,从指定流stream读取单个字符,区别在于其是宏而非函数 |
| getchar(函数) | int getchar(void) | 等同于fgetc(stdin),从标准输入(键盘)读取单个字符 |
(二)返回值
成功时返回读取的字符;若到文件末尾或出错时返回EOF(值为-1)。
(三)注意事项
- 函数返回值为
int类型而非char类型,主要目的是扩展返回值的范围,以区分正常字符和EOF。 stdin是系统定义好的FILE *类型指针,指向标准输入(即键盘输入)。- 打开文件后进行读取操作时,默认从文件开头开始读,每读取一个字符,读写指针会自动后移,操作时需注意文件当前位置。
- 调用
getchar函数时,程序会进入阻塞状态,等待用户通过键盘输入字符。
二、字符输出(写单个字符)
(一)相关函数
| 函数/宏 | 格式 | 功能说明 |
|---|---|---|
| fputc(函数) | int fputc(int c, FILE *stream) | 将字符c(以int类型传入)写入指定流stream |
| putc(宏) | int putc(int c, FILE *stream) | 作用与fputc类似,将字符c写入指定流stream |
| putchar(函数) | int putchar(int c) | 等同于fputc(c, stdout),将字符c写入标准输出(通常为屏幕) |
(二)返回值
成功时返回写入的字符;出错时返回EOF。
(三)注意事项
- 函数的输入参数(待写入字符)和返回值均为
int类型。 - 若出现“Bad file descriptor”错误,大概率是文件打开模式错误,例如以只读模式打开文件却进行写操作,或以只写模式打开文件却进行读操作。
三、行输入(读取整个行)
(一)相关函数
| 函数 | 格式 | 功能说明 |
|---|---|---|
| gets(已淘汰) | char *gets(char *s) | 从标准输入读取一行内容到缓冲区s,因存在缓冲区溢出风险,已被淘汰 |
| fgets(推荐使用) | char *fgets(char *s, int size, FILE *stream) | 从指定流stream读取内容到缓冲区s |
(二)返回值
成功时返回缓冲区指针s;到文件末尾或出错时返回NULL。
(三)功能特点与注意事项
- 读取结束条件:当遇到
'\n'(换行符),或已读取size-1个字符时,函数停止读取并返回,且会在读取内容的末尾自动添加'\0'(字符串结束标志)。 - 对于
fgets函数:- 若输入的数据超出
size限制,仅会将size-1个字符保存到缓冲区,最后添加'\0'。 - 若输入数据少于
size-1个字符,读取到换行符后停止,换行符会被保留在缓冲区中,随后添加'\0'。
- 若输入的数据超出
四、行输出(写整行)
(一)相关函数
| 函数 | 格式 | 功能说明 |
|---|---|---|
| puts | int puts(const char *s) | 将缓冲区s中的字符串输出到标准输出(stdout,通常为屏幕),并在字符串末尾自动追加'\n'(换行符) |
| fputs | int fputs(const char *s, FILE *stream) | 将缓冲区s中的字符串输出到指定流stream,不会在字符串末尾追加'\n' |
(二)返回值
成功时返回非负整数;出错时返回EOF。
五、二进制读写
(一)文本文件与二进制文件的区别
核心区别在于存储格式:文本文件仅能存储文本内容,其数据以字符编码形式存储;二进制文件可存储任意类型数据(如图片、音频、程序数据等),数据以二进制形式直接存储。
(二)计算机内码概念
文本符号在计算机内部需通过特定编码(如ASCII、UTF-8等)转换为数字(二进制形式0和1)才能存储,这种用于表示文本符号的数字编码即计算机内码。
(三)二进制读写函数
- fread(读取函数)
- 格式:
size_t fread(void *ptr, size_t size, size_t n, FILE *fp) - 参数说明:
void *ptr:指向存储读取内容的缓冲区的指针。size_t size:每次读取的数据块的字节大小。size_t n:计划读取的数据块的个数。FILE *fp:指向待读取文件的文件指针。
- 格式:
- fwrite(写入函数)
- 格式:
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp) - 参数说明:
void *ptr:指向待写入文件的数据的缓冲区的指针。size_t size:每次写入的数据块的字节大小。size_t n:计划写入的数据块的个数。FILE *fp:指向待写入文件的文件指针。
- 格式:
(四)注意事项
文件写入操作完成后,文件指针会自动指向文件末尾。若此时直接进行读取操作,将无法读取到文件内容。解决办法有两种:一是通过后续讲解的方法移动文件指针到文件头;二是关闭文件后重新打开,文件指针会重置到文件开头。


























要实现该需求,我们可以通过文件追加写入、时间格式化、信号处理来完成。以下是详细的代码实现及解释:
代码实现
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>FILE *fp = NULL;
int current_num = 0;// 信号处理函数:捕获Ctrl-C中断,确保文件关闭
void sigint_handler(int sig) {if (fp != NULL) {fclose(fp);printf("\n程序中断,文件已安全关闭\n");}exit(0);
}int main() {// 注册Ctrl-C信号处理函数signal(SIGINT, sigint_handler);// 以“追加+读写”模式打开文件(a+模式:允许读写,且写入时自动追加到末尾)fp = fopen("test.txt", "a+");if (fp == NULL) {perror("文件打开失败");exit(1);}// 将文件指针移到开头,读取已有最大序号fseek(fp, 0, SEEK_SET);char line[100];int num;while (fgets(line, sizeof(line), fp) != NULL) {if (sscanf(line, "%d,", &num) == 1) { // 提取行首的序号if (num > current_num) {current_num = num;}}}current_num++; // 下一个序号从已有最大值+1开始// 无限循环写入时间while (1) {// 获取并格式化当前系统时间time_t now = time(NULL);struct tm *tm_now = localtime(&now);char time_str[50];strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_now);// 写入文件(带序号和时间)fprintf(fp, "%d, %s\n", current_num, time_str);fflush(fp); // 立即刷新缓冲区,确保内容写入文件printf("已写入:%d, %s\n", current_num, time_str);current_num++;sleep(1); // 休眠1秒}fclose(fp); // 理论上不会执行到此处,因循环是无限的return 0;
}
代码解释
- 信号处理:通过
signal(SIGINT, sigint_handler)注册Ctrl-C(SIGINT信号)的处理函数,确保程序中断时能关闭文件,避免数据丢失。 - 文件打开与序号读取:
- 以
"a+"模式打开test.txt,该模式支持读写操作,且写入时自动追加到文件末尾。 - 通过
fseek(fp, 0, SEEK_SET)将文件指针移到开头,逐行读取已有内容,提取最大序号,保证下次写入时序号连续递增。
- 以
- 时间格式化与写入:
- 用
time(NULL)获取当前时间戳,localtime转换为本地时间结构,strftime格式化时间为"年-月-日 时:分:秒"格式。 - 用
fprintf将“序号+时间”写入文件,fflush强制刷新缓冲区,确保内容立即写入磁盘。
- 用
- 循环与休眠:
while(1)无限循环,每次循环后sleep(1)实现1秒间隔。
运行效果
- 首次运行:文件从序号
1开始,每隔1秒追加一行时间,格式如"1, 2025-10-29 10:00:00"。 - 中断后再次运行:程序会自动读取已有最大序号,从下一个序号继续追加(例如上次最大是
5,本次从6开始)。 - 按
Ctrl-C中断时,文件会被安全关闭,已写入内容不会丢失。
该程序完全满足“每隔1秒追加时间、序号递增、Ctrl-C中断”的需求,且保证了文件操作的安全性。












































