文件操作
打开和关闭操作
**打开文件(fopen)**FILE *fopen(const char *filename, const char *mode);
mode(资料来源AI):
模式 描述 创建文件 清空原内容 文件指针起始位置 可读? 可写? "r"
只读模式 ❌ 否 ❌ 否 文件开头 ✅ 是 ❌ 否 "w"
写入模式(覆盖) ✅ 是 ✅ 是(清空已有内容) 文件开头 ❌ 否 ✅ 是 "a"
追加写入模式 ✅ 是 ❌ 否(保留原内容) 文件末尾 ❌ 否 ✅ 是 "r+"
读写模式 ❌ 否 ❌ 否 文件开头 ✅ 是 ✅ 是 "w+"
读写模式(覆盖/新建) ✅ 是 ✅ 是 文件开头 ✅ 是 ✅ 是 "a+"
读写模式(追加) ✅ 是 ❌ 否 文件末尾 ✅ 是 "rb"
以二进制只读方式打开 "wb"
以二进制写入方式打开(清空) "ab"
以二进制追加方式打开 "rb+"
以二进制读写方式打开 "wb+"
以二进制读写方式打开(清空) "ab+"
以二进制读写方式打开(追加)
#include <stdio.h>
int main()
{
FILE *fp;
// 以只读方式打开文件
fp = fopen("022.txt", "r");
if (fp == NULL)
{
printf("Error: 文件打开失败!");
return 0;
}
else
{
printf("File opened successfully\n");
fclose(fp); // 使用完后关闭文件
}
return 0;
}
关闭文件(fclose): 操作完成后 一定要关闭 文件!
读写文件操作
读写文件(fread / fwrite / fscanf / fprintf / fgets / fputs 等)
单字符 读写
逐字符读写:
fgetc
/fputc
int fgetc(FILE *stream); // 读取一个字符
int ch; while ((ch = fgetc(fp))!= EOF) { printf("%c", ch); }
int fputc(int c, FILE *stream); // 写入一个字符
FILE *fp; // 写入文件 fp = fopen("0235.txt", "w"); fputc('B', fp); //写入一个字符
行 读写
行级读写:fgets
/ fputs
#include <stdio.h>
int main()
{
FILE *fp;
fp = fopen("0235.txt", "r");
char line[1024];
printf ("%s", fgets(line, sizeof(line), fp)); //读取一行
}
写入一行
#include <stdio.h>
int main()
{
FILE *fp;
fp = fopen("0235.txt", "w");
char line[1024]="hello world";
fputs(line, fp); //写入一行
fclose(fp);
fp = fopen("0235.txt", "r");
char rline[1024];
printf ("%s",fgets(rline,1024,fp) );//读取一行
fclose(fp);
}
格式化读写
格式化读写:fscanf
/ fprintf
写入和读取结构体数据(文本格式)
#include <stdio.h>
void redefile(FILE *fp);//读取文件并输出函数声明
typedef struct {
int id;
char name[50];
}Stdu;
Stdu s1= {1,"wangwei"};
int main()
{
FILE *fp;
fp = fopen("0235.txt", "w+");
if(fp!=NULL)
{
fprintf(fp,"%d %s \n",s1.id,s1.name);//写入结构体 文本
fclose(fp);
redefile(fp);
}
}
void redefile(FILE *fp)
{
fp=fopen("0235.txt","r");
if(fp!=NULL)
{
char lile[1024];
printf("%s",fgets(lile,1024,fp));
fclose(fp);
}
}
//============================输出效果
1 wangwei
写入和读取结构体数据(文本格式)
int fscanf(FILE *stream, const char *format, ...);
#include <stdio.h>
void redefile();
typedef struct {
int id;
char name[50];
}Stdu;
Stdu s1= {1,"wangwei"};
int main()
{
FILE *fp;
fp = fopen("0235.txt", "w+");
if(fp!=NULL)
{
fprintf(fp,"%d %s \n",s1.id,s1.name); //写入
fclose(fp);
redefile();
}
}
void redefile()
{
FILE *fp;
fp=fopen("0235.txt","r");
char lien[1024];
if(fp!=NULL)
{
if(fscanf(fp,"%d %s",&s1.id,s1.name)==2)//查找
{
printf("....\n");
}
rewind(fp);//返回文件开头
printf(" %s \n",fgets(lien,1024,fp));//读取输出
fclose(fp);
}
}
- 成功匹配并赋值的输入项数量(例如读取了
%d %s
,返回2
) - 如果到达文件末尾或发生错误,返回
EOF
二进制读写:fread
/ fwrite
#include <stdio.h>
// 函数声明:redefile 用于从二进制文件中读取结构体数据
void redefile();
// 定义一个结构体类型 Stdu(学生)
typedef struct {
int id; // 学生 ID
char name[50]; // 学生姓名(固定长度字符数组)
} Stdu;
// 定义一个全局变量 s1,并初始化
Stdu s1 = {1, "wangwei"}; // 初始 ID 为 1,姓名为 "wangwei"
int main()
{
// 声明一个文件指针 fp
FILE *fp;
// 以 "w+" 模式打开文件(可读写,清空或新建文件)
// 文件名为 "0235.dat",通常 .dat 表示二进制数据文件
fp = fopen("0235.dat", "w+");
if (fp != NULL)
{
// 使用 fwrite 将结构体 s1 写入文件
// 参数说明:
// &s1 -> 要写入的结构体地址
// sizeof(Stdu) -> 每个结构体的大小
// 1 -> 写入 1 个结构体
// fp -> 文件指针
fwrite(&s1, sizeof(Stdu), 1, fp);
// 关闭文件流
fclose(fp);
// 调用函数 redefile(),用于从文件中读取并打印结构体内容
redefile();
}
return 0;
}
/**
* 函数名称:redefile
* 功能:打开二进制文件并读取其中的结构体数据
*/
void redefile()
{
// 声明一个新的文件指针 fp
FILE *fp;
// 以只读二进制模式 ("rb") 打开之前写入的文件
fp = fopen("0235.dat", "rb");
// 判断文件是否成功打开
if (fp != NULL)
{
// 声明一个结构体变量 s,用于接收读取的数据
Stdu s;
// 使用 fread 循环读取结构体数据
// fread 返回值是成功读取的结构体数量,等于 1 表示读取成功
while (fread(&s, sizeof(Stdu), 1, fp) == 1)
{
// 打印读取到的学生信息
printf("ID: %d, Name: %s\n", s.id, s.name);
}
// 关闭文件流
fclose(fp);
}
else
{
// 如果文件打开失败,输出提示信息
printf("无法打开文件进行读取\n");
}
}
定位文件操作
定位文件位置(fseek / ftell / rewind)
|-----------------------------|---------------|---------------------------|
| fseek(fp, offset, whence)
| 设置文件指针位置 | fseek(fp, 10, SEEK_SET)
|
| ftell(fp)
| 获取当前文件指针位置 | long pos = ftell(fp);
|
| rewind(fp)
| 回到文件开头 | rewind(fp);
|
| fflush(fp)
| 刷新缓冲区(适用于输出流) | fflush(fp);
|
fseek函数参数详解:
|------|----------|--------------------------|
| fp
| FILE *
| 文件指针,必须先用 fopen()
打开文件 |
|----------|--------|----------------------------------------------|
| offset
| long
| 偏移量(字节数),可为正也可为负 |
| whence
| int
| 定位起始点,取值为 SEEK_SET
, SEEK_CUR
, SEEK_END
|
whence 值 | 含义 |
---|---|
SEEK_SET |
文件开头 |
SEEK_CUR |
当前位置 |
SEEK_END |
文件末尾 |
获取文件大小操作
#include <stdio.h>
void redefile();
typedef struct {
int id;
char name[50];
}Stdu;
Stdu s1= {1,"wangwei"};
int main()
{
FILE *fp;
fp = fopen("0235.txt", "w");
if(fp!=NULL)
{
fputs("This is test",fp);//写入一行到文件中
fclose(fp);
redefile();
}
}
void redefile()
{
FILE *fp;
fp=fopen("0235.txt","r");
fseek(fp,0,SEEK_END);//移动文件指针 设置指针位置0 为文件末尾
long dft=ftell(fp);//获取文件指针位置
printf("Size:%ld\n",dft);//输出文件指针位置
char buf[1024];
rewind(fp);//回到文件开头位置
printf("%s",fgets(buf,1024,fp));//读取一行并输出
fclose(fp);
}
运行后输出效果为:

重点小知识:
fopen()
默认在 Windows 上使用的是 ANSI 编码(即 GBK)- 所以当你的程序从 UTF-8 编码的源文件中编译时,
fopen()
会把"5改.mix"
当作 UTF-8 编码的字符串,但实际 Windows API 要求的是 GBK 或 UTF-16- 结果就是:文件名解析失败,返回
NULL
解决办法:
|-----------------------------|---------------------------------|
|_wfopen(L"中文,文件名", L "r")
| 使用宽字符字符串,兼容 Windows Unicode API |
FILE *fp; fp=_wfopen(L"中文,文件名",L"r");