C语言文件操作:从打开到关闭的完整指南

C语言文件操作:从打开到关闭的完整指南

文件操作是C语言编程中至关重要的技能,它允许程序与外部存储设备进行数据交换。无论是读取配置文件、保存用户数据,还是处理日志文件,都离不开文件操作。本篇博客将深入讲解C语言文件操作的核心概念、常用函数及最佳实践,帮助你全面掌握这一关键技能。

一、文件指针:文件操作的核心

C语言通过文件指针(FILE*)来操作文件。文件指针是一个结构体指针,指向一个包含文件状态信息的结构体。所有文件操作函数都需要文件指针作为参数。

C
1
FILE* fp; // 声明一个文件指针

二、fopen():打开文件

fopen()函数用于打开文件,返回一个文件指针。其原型如下:

C
1
FILE* fopen(const char* filename, const char* mode);

打开模式

  • "r":只读模式(文件必须存在)
  • "w":只写模式(创建新文件或清空现有文件)
  • "a":追加模式(在文件末尾添加)
  • "r+":读写模式(文件必须存在)
  • "w+":读写模式(创建新文件或清空现有文件)
  • "a+":读写追加模式(在文件末尾读写)

二进制模式在模式字符串后加"b",如"rb""wb"

示例

C
1
2
3
4
5
FILE* fp = fopen("data.txt", "r");
if (fp == NULL) {
printf("无法打开文件!\n");
return 1;
}

三、标准流:预定义的文件指针

C语言预定义了三个标准流:

  1. stdin:标准输入(通常是键盘)
  2. stdout:标准输出(通常是屏幕)
  3. stderr:标准错误输出

这些流在程序启动时自动打开,无需fopen()

四、fclose():关闭文件

fclose()函数关闭文件并释放资源。非常重要:每个打开的文件都必须关闭。

C
1
int fclose(FILE* fp);

关闭成功返回0,失败返回EOF

五、EOF:文件结束标志

EOF(End Of File)是一个宏定义,值为-1。当文件读取函数遇到文件末尾时返回EOF

C
1
2
3
4
int ch;
while ((ch = fgetc(fp)) != EOF) {
putchar(ch);
}

六、文件读写函数

1. 字符级I/O
  • fgetc() / getc():从文件读取一个字符
  • fputc() / putc():向文件写入一个字符
C
1
2
3
4
5
// 读取
int c = fgetc(fp);

// 写入
fputc('A', fp);
2. 字符串级I/O
  • fgets():从文件读取一行字符串
  • fputs():向文件写入字符串(不自动添加换行符)
C
1
2
3
4
5
6
char buffer[100];
// 读取最多99个字符或遇到换行符
fgets(buffer, sizeof(buffer), fp);

// 写入字符串
fputs("Hello, World!", fp);
3. 格式化I/O
  • fprintf():格式化写入文件
  • fscanf():格式化读取文件
C
1
2
3
4
5
6
7
// 写入
fprintf(fp, "%s %d %.2f\n", "Alice", 25, 95.5);

// 读取
char name[50];
int age;
fscanf(fp, "%s %d", name, &age);
4. 二进制I/O
  • fwrite():写入二进制数据
  • fread():读取二进制数据
C
1
2
3
4
5
6
7
8
9
10
11
struct Student {
char name[50];
int age;
float score;
} stu;

// 写入
fwrite(&stu, sizeof(struct Student), 1, fp);

// 读取
fread(&stu, sizeof(struct Student), 1, fp);

七、文件定位函数

1. fseek():移动文件指针
C
1
int fseek(FILE* fp, long offset, int whence);

whence参数

  • SEEK_SET:文件开头
  • SEEK_CUR:当前位置
  • SEEK_END:文件末尾

示例

C
1
2
fseek(fp, 0, SEEK_SET); // 移动到文件开头
fseek(fp, -10, SEEK_END); // 移动到文件末尾前10字节
2. ftell():获取当前位置
C
1
long ftell(FILE* fp);

返回当前位置相对于文件开头的字节偏移量。

3. rewind():重置到文件开头
C
1
void rewind(FILE* fp);

等价于fseek(fp, 0, SEEK_SET)

4. fgetpos()和fsetpos():大文件定位

对于超过4GB的大文件,使用这两个函数:

C
1
2
3
4
fpos_t pos;
fgetpos(fp, &pos); // 获取位置
// ... 文件操作 ...
fsetpos(fp, &pos); // 恢复位置

八、文件状态检查

1. feof():检查文件结束
C
1
int feof(FILE* fp);

到达文件末尾时返回非零值。

2. ferror()和clearerr():错误处理
C
1
2
int ferror(FILE* fp); // 检查错误
void clearerr(FILE* fp); // 清除错误状态

错误处理模式

C
1
2
3
4
5
6
7
8
9
if (fscanf(fp, "%d", &n) != 1) {
if (ferror(fp)) {
printf("输入输出错误\n");
}
if (feof(fp)) {
printf("文件结束\n");
}
clearerr(fp); // 清除错误状态
}

九、文件管理函数

1. remove():删除文件
C
1
int remove(const char* filename);

删除成功返回0,失败返回非零值。

注意:必须先关闭文件再删除。

2. rename():重命名或移动文件
C
1
int rename(const char* old_filename, const char* new_filename);

可以用于重命名或移动文件。

C
1
2
rename("old.txt", "new.txt"); // 重命名
rename("/tmp/file.txt", "/home/user/file.txt"); // 移动文件

十、文件操作最佳实践

  1. 总是检查fopen()的返回值:文件可能不存在或无权限访问。
  2. 及时关闭文件:避免资源泄漏和文件锁定问题。
  3. 处理错误情况:使用ferror()feof()进行错误诊断。
  4. 区分文本和二进制模式:Windows系统上,文本模式会处理换行符转换。
  5. 使用缓冲区:大规模文件操作时,设置适当的缓冲区可以提高性能。
C
1
2
3
// 设置缓冲区示例
char buffer[4096];
setvbuf(fp, buffer, _IOFBF, sizeof(buffer));
  1. 安全的字符串读取:使用fgets()代替已废弃的gets()
  2. 检查格式化输入输出:验证fscanf()fprintf()的返回值。

十一、综合示例:文件复制程序

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>

int main() {
FILE* src = fopen("source.txt", "r");
if (src == NULL) {
perror("无法打开源文件");
return 1;
}

FILE* dst = fopen("destination.txt", "w");
if (dst == NULL) {
perror("无法创建目标文件");
fclose(src);
return 1;
}

int ch;
while ((ch = fgetc(src)) != EOF) {
fputc(ch, dst);
}

if (ferror(src)) {
printf("读取源文件时发生错误\n");
}
if (ferror(dst)) {
printf("写入目标文件时发生错误\n");
}

fclose(src);
fclose(dst);
printf("文件复制完成!\n");

return 0;
}

十二、总结

掌握C语言文件操作是成为熟练C程序员的关键一步。记住核心要点:

  • 文件指针是所有文件操作的基础
  • 打开模式决定了文件的访问方式
  • 及时关闭文件避免资源泄漏
  • 错误检查确保程序的健壮性
  • 选择合适的函数根据需求(字符、字符串、格式化、二进制)
  • 文件定位提供了灵活的访问控制
  • 标准库函数提供了丰富的文件管理功能

通过理解这些概念并实践示例代码,你将能够自信地在C程序中处理各种文件操作任务。


C语言文件操作:从打开到关闭的完整指南
https://www.edenzeng.online/2015/11/11/0.技术栈/01.开发语言/01.C语言/17-文件操作详解/
作者
Edenzeng
发布于
2015年11月11日
许可协议