文件IO (持续更新)
文件IO
1、 fopen -> 文件打开
-
参数:
-
pathname:文件路径 -
mode:打开模式(见下表)
-
-
模式说明:
模式 描述 文件存在 文件不存在 "r" 只读(文本文件) 打开 失败 "w" 只写(清空文件) 清空 创建 "a" 追加写入(文本文件) 追加 创建 "r+" 读写(文本文件) 打开 失败 "w+" 读写(清空文件) 清空 创建 "a+" 读写(追加模式) 追加 创建 "b" 二进制模式(如 "rb+") -
示例:
FILE *fp = fopen("data.txt", "r"); if (fp == NULL) { perror("文件打开失败"); exit(EXIT_FAILURE); } -
注意:
-
始终检查返回值是否为
NULL -
跨平台时建议使用二进制模式(如 Windows 的换行符问题)
-

2、 fclose ->文件关闭
int fclose(FILE *stream);
-
参数:
stream- 要关闭的文件指针 -
返回值:成功返回
0,失败返回EOF -
示例:
if (fclose(fp) != 0) { perror("关闭文件失败"); } -
注意:
-
关闭后文件指针不再可用
-
未关闭文件可能导致数据丢失或资源泄漏
-
3、 fgetc -> 字符读
int fgetc(FILE *stream);
-
参数:
stream- 文件指针 -
返回值:
-
成功返回读取的字符(转为
unsigned char再转int) -
失败或 EOF 返回
EOF
-
-
示例:
int c; while ((c = fgetc(fp)) != EOF) { putchar(c); } -
注意:
-
必须用
int接收返回值,char类型无法区分EOF和0xFF
-
4、 fgets -> 字符串读
char *fgets(char *str, int size, FILE *stream);
-
参数:
-
str:存储读取数据的缓冲区 -
size:缓冲区大小(包含结尾的\0) -
stream:文件指针
-
-
返回值:
-
成功返回
str -
失败或 EOF 返回
NULL
-
-
示例:
char buffer[256]; if (fgets(buffer, sizeof(buffer), fp) != NULL) { printf("读取内容: %s", buffer); } -
注意:
-
读取到
\n或缓冲区满时停止 -
保留换行符并在末尾添加
\0
-
5、 fread -> 读文件
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
-
参数:
-
ptr:数据存储缓冲区 -
size:每个数据项的字节数 -
nmemb:要读取的数据项数量 -
stream:文件指针
-
-
返回值:实际读取的数据项数量(可能小于
nmemb) -
示例:
int data[10]; size_t read_count = fread(data, sizeof(int), 10, fp); -
注意:
-
推荐用
sizeof计算size(思考一下sizeof会把字符串中'\0'计算在内吗?) -
需检查返回值是否等于预期数量
-
6、 fputc -> 字符写
int fputc(int c, FILE *stream);
-
参数:
-
c:要写入的字符(转为unsigned char) -
stream:文件指针
-
-
返回值:成功返回写入的字符,失败返回
EOF -
示例:
fputc('A', fp); // 写入字符'A'
7、 fputs -> 字符串写
int fputs(const char *s, FILE *stream);
-
参数:
-
s:要写入的字符串(需包含换行符) -
stream:文件指针
-
-
返回值:成功返回非负数,失败返回
EOF -
示例:
fputs("Hello World\n", fp); -
注意:
-
不会自动添加换行符
-
字符串需以
\0结尾
-
8、 fwrite -> 写文件
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
-
参数:
-
ptr:数据存储缓冲区 -
size:每个数据项的字节数 -
nmemb:要读取的数据项数量 -
stream:文件指针
-
-
返回值:实际写入的数据项数量
-
示例:
int data[] = {1, 2, 3}; fwrite(data, sizeof(int), 3, fp); -
注意:
-
数据写入可能因磁盘满等原因部分成功
-
二进制文件需用相同模式读写(如结构体序列化)
-
9、 fflush -> 刷新缓冲区
int fflush(FILE *stream);
-
功能:强制将缓冲区数据写入文件
-
注意:
-
对输入流使用行为未定义
-
频繁调用可能影响性能
-
10、 fseek/ftell -> fseek移动光标/ftell计算当前光标距离文件开头的距离
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
-
whence参数:-
SEEK_SET:文件开头 -
SEEK_CUR:当前位置 SEEK_END:文件末尾
-
- 示例:
fseek(fp, 0, SEEK_END); // 定位到文件末尾
long size = ftell(fp); // 获取文件大小
11、 feof -> 检测文件结束标志
int feof(FILE *stream);
-
功能:检测文件流的 文件结束标志(end-of-file indicator) 是否被置位。
-
参数:
stream- 文件指针(指向已打开的文件流)。 -
返回值:
-
如果文件结束标志被置位(即尝试读取时已到达文件末尾),返回 非零值。
-
否则返回
0。
-
12、 ferror -> 检测文件错误标志
int ferror(FILE *stream);
-
功能:检测文件流的 错误标志(error indicator) 是否被置位。
-
参数:
stream- 文件指针。 -
返回值:
-
如果错误标志被置位(如磁盘I/O错误、非法操作),返回 非零值。
-
否则返回
0。
-
-
通常与
feof结合使用,区分“正常结束”和“异常终止”。
例1:向log文件写入当前的时间 👇代码
这个感觉有点意思的
#include<stdio.h>
#include<time.h>
#include<unistd.h>
#include<stdlib.h>
int main(int argc,char const * argv[]){
// if(2 != argc){
// printf("argument is invalid\n");
// }
FILE * log = fopen("log.txt","wd");
if (!log) {
perror("无法打开日志文件");
exit(-1);
}
while(1){
//获取时间
time_t now;
time(&now);
struct tm *tm_info = localtime(&now);
//把当前时间按照 --yy年mm月dd日--来输入到log.txt文件
fprintf(log,"%d年%d月%d日%d时%d分%d秒\n",(tm_info->tm_year+1900),tm_info->tm_mon,tm_info->tm_mday,tm_info->tm_hour,tm_info->tm_min,tm_info->tm_sec);
fflush(log); // 立即刷新缓冲区确保数据写入
sleep(1);//休眠1秒
printf("*******正在写入*******\n");
}
fclose(log);
return 1;
}
例2:计算文件的大小 👇代码
/*************************************************************************
* file name:CalculateFileSize
* function: 计算文件的大小
* date: 2025.5.21
* note:需要在执行文件时 写入所计算文件的名字
* 例:
* ./main a.txt
* Copyright (c) 2024-2025 l550036303@163.com All right reserved
**************************************************************************/
#include<stdio.h>
#include<stdlib.h>
void main(int argc,char const * argv[]){
/************************************第一种方法计算******************************************/
#if 0
long int number=0;
if( 2 !=argc ){
perror("argument is invail");
exit(-1);
}
FILE * p = fopen(argv[1],"rb");
if( NULL == p ){
perror("无法打开文件");
exit(-1);
}
while((fgetc(p)) != EOF ){
number++;
}
// printf("\tfilename: %s\tsize:%d\n",argv[1],number);
if(ferror(p) != 0){
perror("读取文件时发生错误");
fclose(p);
exit(-1);
}
if(feof(p) != 0){
printf("\tfilename: %s\tsize:%ld\n",argv[1],number);
}
#endif
/************************************第二种方法计算******************************************/
#if 0
long int number=0;
if( 2 !=argc ){
perror("argument is invail");
exit(-1);
}
FILE * p = fopen(argv[1],"ab");
if( NULL == p ){
perror("无法打开文件");
exit(-1);
}
number = ftell(p);
if(ferror(p) != 0){ //ferror 为0时就是无异常
perror("读取文件时发生错误");
fclose(p);
exit(-1);
}
printf("\tfilename: %s\tsize:%ld\n",argv[1],number);
#endif
/************************************第三种方法计算******************************************/
#if 1
long int number=0;
if( 2 !=argc ){
perror("argument is invail");
exit(-1);
}
FILE * p = fopen(argv[1],"rb");
if( NULL == p ){
perror("无法打开文件");
exit(-1);
}
fseek(p,0,SEEK_END); //移动光标到末尾 CUR当前 SET开头
number = ftell(p);
if(ferror(p) != 0){ //ferror 为0时就是无异常
perror("读取文件时发生错误");
fclose(p);
exit(-1);
}
printf("\tfilename: %s\tsize:%ld\n",argv[1],number);
#endif
/******************************************************************************/
//关闭
fclose(p);
return;
}
例3:复制文件 👇代码
/*************************************************************************
* file name:creatlog
* function: source文件的内容复制到 target文件
* date: 2025.5.22
* note: 要输入两个文件名 第一个是source名 第二个是target文件名 ./creatlog io.c copytest.c
* Copyright (c) 2024-2025 l550036303@163.com All right reserved
**************************************************************************/
#include<stdio.h>
#include<stdlib.h>
void main(int argc,char const *argv[]){
if(3 != argc){
perror("argument is invail\n");
exit(-1);
}
FILE* src = fopen(argv[1],"rb");
FILE* tar = fopen(argv[2],"wb");
if( src == NULL ){
printf("%s open fail\n",argv[1]);
exit(-1);
}
if( tar == NULL){
printf("%s open fail\n",argv[2]);
exit(-1);
}
char temp[5];
int n = 0;
while((n=fread(temp,1,sizeof(temp),src) ) > 0){
fwrite(temp,1,n,tar);
if (ferror(tar)) {
perror("写入目标文件失败");
fclose(src);
fclose(tar);
exit(-1);
}
}
if (ferror(src)) {
perror("读取源文件失败");
fclose(src);
fclose(tar);
exit(-1);
}
fclose(src);
fclose(tar);
return;
}

浙公网安备 33010602011771号