1. fileoperationoverview
1.1 what is file
file is store in out 部store设备 (such as硬盘, U盘etc.) on 一组相关data collection. in Clanguagein, file可以分 for 两种class型:
- 文本file: 以字符形式storedata, 每个字符 for 应一个ASCII码值, 适合store可阅读 文本data.
- 二进制file: 以二进制形式storedata, 直接storedata 二进制表示, 适合storegraph像, 音频, 视频etc.非文本data, 以及需要 high 效store 数值data.
1.2 file指针
in Clanguagein, fileoperation is throughfile指针来for . file指针 is a 指向FILEclass型structure 指针, FILEstructure定义 in stdio.h头filein, package含了file 相关information, such asfile 位置指针, file 打开模式etc..
// 声明file指针 FILE *fp;
2. file 打开 and 关闭
2.1 file 打开
usingfopenfunction打开file, 该function 原型such as under :
FILE *fopen(const char *filename, const char *mode);
其in:
filename: 要打开 file path and 名称.mode: file 打开模式, 指定了file operation方式.- return value: 成功打开file时, 返回指向该file file指针; 失败时, 返回
NULL.
常用 file打开模式:
"r" - 只读模式, 打开一个已存 in 文本file "w" - 只写模式, creation一个 new 文本file, such as果file已存 in 则清空其 in 容 "a" - 追加模式, 打开一个文本file, in file末尾添加data, such as果file不存 in 则creation "rb" - 只读模式, 打开一个已存 in 二进制file "wb" - 只写模式, creation一个 new 二进制file, such as果file已存 in 则清空其 in 容 "ab" - 追加模式, 打开一个二进制file, in file末尾添加data, such as果file不存 in 则creation "r+" - 读写模式, 打开一个已存 in 文本file "w+" - 读写模式, creation一个 new 文本file, such as果file已存 in 则清空其 in 容 "a+" - 读写模式, 打开一个文本file, in file末尾添加data, such as果file不存 in 则creation "rb+" - 读写模式, 打开一个已存 in 二进制file "wb+" - 读写模式, creation一个 new 二进制file, such as果file已存 in 则清空其 in 容 "ab+" - 读写模式, 打开一个二进制file, in file末尾添加data, such as果file不存 in 则creation
2.2 file 关闭
usingfclosefunction关闭file, 该function 原型such as under :
int fclose(FILE *stream);
其in:
stream: 要关闭 file指针.- return value: 成功关闭file时, 返回0; 失败时, 返回EOF (-1) .
关闭file important 性:
- 释放file指针占用 resource
- 确保所 has 缓冲区 data被写入file
- 防止file被other程序占用
2.3 example: 打开 and 关闭file
#include <stdio.h>
int main() {
FILE *fp;
// 打开file
fp = fopen("test.txt", "w");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
printf("file打开成功\n");
// 关闭file
if (fclose(fp) == 0) {
printf("file关闭成功\n");
} else {
printf("file关闭失败\n");
}
return 0;
}
3. 文本file 读写operation
3.1 写入文本file
常用 写入文本file function:
3.1.1 fprintffunction
int fprintf(FILE *stream, const char *format, ...);
and printffunctionclass似, 但 is 将输出写入 to 指定 filein.
#include <stdio.h>
int main() {
FILE *fp;
int num = 100;
float score = 95.5;
char name[] = "张三";
// 打开file
fp = fopen("test.txt", "w");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
// 写入data
fprintf(fp, "姓名: %s\n", name);
fprintf(fp, "年龄: %d\n", num);
fprintf(fp, "成绩: %.1f\n", score);
// 关闭file
fclose(fp);
printf("data写入成功\n");
return 0;
}
3.1.2 fputsfunction
int fputs(const char *s, FILE *stream);
将string写入 to 指定 filein.
#include <stdio.h>
int main() {
FILE *fp;
char str[] = "Hello, World!";
// 打开file
fp = fopen("test.txt", "w");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
// 写入string
fputs(str, fp);
fputs("\n", fp); // 写入换行符
fputs("Welcome to C programming!", fp);
// 关闭file
fclose(fp);
printf("string写入成功\n");
return 0;
}
3.1.3 putcfunction
int putc(int c, FILE *stream);
将单个字符写入 to 指定 filein.
#include <stdio.h>
int main() {
FILE *fp;
char ch;
// 打开file
fp = fopen("test.txt", "w");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
// 写入字符
for (ch = 'A'; ch <= 'Z'; ch++) {
putc(ch, fp);
}
putc('\n', fp); // 写入换行符
// 关闭file
fclose(fp);
printf("字符写入成功\n");
return 0;
}
3.2 读取文本file
常用 读取文本file function:
3.2.1 fscanffunction
int fscanf(FILE *stream, const char *format, ...);
and scanffunctionclass似, 但 is from 指定 filein读取输入.
#include <stdio.h>
int main() {
FILE *fp;
char name[50];
int age;
float score;
// 打开file
fp = fopen("test.txt", "r");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
// 读取data
fscanf(fp, "姓名: %s\n", name);
fscanf(fp, "年龄: %d\n", &age);
fscanf(fp, "成绩: %f\n", &score);
// 输出读取 data
printf("读取 data:\n");
printf("姓名: %s\n", name);
printf("年龄: %d\n", age);
printf("成绩: %.1f\n", score);
// 关闭file
fclose(fp);
return 0;
}
3.2.2 fgetsfunction
char *fgets(char *s, int size, FILE *stream);
from 指定 filein读取一行字符, store to 字符arrayin.
#include <stdio.h>
int main() {
FILE *fp;
char buffer[100];
// 打开file
fp = fopen("test.txt", "r");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
// 读取file in 容
printf("file in 容:\n");
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("%s", buffer);
}
// 关闭file
fclose(fp);
return 0;
}
3.2.3 getcfunction
int getc(FILE *stream);
from 指定 filein读取单个字符.
#include <stdio.h>
int main() {
FILE *fp;
int ch;
// 打开file
fp = fopen("test.txt", "r");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
// 读取file in 容
printf("file in 容:\n");
while ((ch = getc(fp)) != EOF) {
putchar(ch);
}
// 关闭file
fclose(fp);
return 0;
}
4. 二进制file 读写operation
4.1 写入二进制file
usingfwritefunction写入二进制file:
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
其in:
ptr: 指向要写入data memory地址.size: 每个data项 big small (以字节 for 单位) .count: 要写入 data项 数量.stream: file指针.- return value: 成功写入 data项 数量.
#include <stdio.h>
int main() {
FILE *fp;
int numbers[] = {10, 20, 30, 40, 50};
int n = sizeof(numbers) / sizeof(numbers[0]);
// 打开二进制file
fp = fopen("data.bin", "wb");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
// 写入data
size_t written = fwrite(numbers, sizeof(int), n, fp);
printf("成功写入 %zu 个整数\n", written);
// 关闭file
fclose(fp);
return 0;
}
4.2 读取二进制file
usingfreadfunction读取二进制file:
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
其in:
ptr: 指向store读取data memory地址.size: 每个data项 big small (以字节 for 单位) .count: 要读取 data项 最 big 数量.stream: file指针.- return value: 成功读取 data项 数量.
#include <stdio.h>
int main() {
FILE *fp;
int numbers[5];
int i;
// 打开二进制file
fp = fopen("data.bin", "rb");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
// 读取data
size_t read = fread(numbers, sizeof(int), 5, fp);
printf("成功读取 %zu 个整数\n", read);
// 输出读取 data
printf("读取 data: ");
for (i = 0; i < read; i++) {
printf("%d ", numbers[i]);
}
printf("\n");
// 关闭file
fclose(fp);
return 0;
}
5. file位置指针 operation
5.1 file位置指针
file位置指针 is a 指向filein当 before 读写位置 指针. 当打开一个file时, file位置指针 初始位置取决于file 打开模式:
- for 于"r", "rb"模式, file位置指针指向file 开头.
- for 于"w", "wb"模式, file位置指针指向file 开头, 并且file被清空.
- for 于"a", "ab"模式, file位置指针指向file 末尾.
5.2 file位置指针 operationfunction
5.2.1 ftellfunction
long ftell(FILE *stream);
获取当 before file位置指针 位置 (相 for 于file开头 偏移量, 以字节 for 单位) .
5.2.2 fseekfunction
int fseek(FILE *stream, long offset, int whence);
设置file位置指针 位置.
其in:
offset: 偏移量, 以字节 for 单位.whence: 基准位置, 取值 for :SEEK_SET: 以file开头 for 基准.SEEK_CUR: 以当 before 位置 for 基准.SEEK_END: 以file末尾 for 基准.
5.2.3 rewindfunction
void rewind(FILE *stream);
将file位置指针reset to file 开头, 相当于fseek(stream, 0, SEEK_SET).
#include <stdio.h>
int main() {
FILE *fp;
char buffer[100];
long position;
// 打开file
fp = fopen("test.txt", "r");
// checkfile is 否成功打开
if (fp == NULL) {
printf("file打开失败\n");
return 1;
}
// 读取第一行
fgets(buffer, sizeof(buffer), fp);
printf("第一行: %s", buffer);
// 获取当 before 位置
position = ftell(fp);
printf("当 before 位置: %ld 字节\n", position);
// 读取第二行
fgets(buffer, sizeof(buffer), fp);
printf("第二行: %s", buffer);
// reset to file开头
rewind(fp);
printf("reset to file开头\n");
// 再次读取第一行
fgets(buffer, sizeof(buffer), fp);
printf("再次读取第一行: %s", buffer);
// usingfseek设置位置
fseek(fp, position, SEEK_SET);
printf("设置 to 之 before 位置\n");
// 再次读取第二行
fgets(buffer, sizeof(buffer), fp);
printf("再次读取第二行: %s", buffer);
// 关闭file
fclose(fp);
return 0;
}
6. fileoperation errorprocessing
6.1 error检测
in forfileoperation时, 应该始终checkfunction return value, 以检测可能发生 error:
- for 于
fopen, checkreturn value is 否 forNULL. - for 于
fclose, checkreturn value is 否 for 0. - for 于
fread,fwrite, checkreturn value is 否etc.于request 数量. - for 于
fscanf,fgetsetc., checkreturn value is 否符合预期.
6.2 errorinformation
usingperrorfunction可以打印 and 当 before error码 for 应 errorinformation:
#include <stdio.h>
int main() {
FILE *fp;
// 尝试打开一个不存 in file
fp = fopen("nonexistent.txt", "r");
// checkfile is 否成功打开
if (fp == NULL) {
perror("file打开失败");
return 1;
}
// 关闭file
fclose(fp);
return 0;
}
7. file delete and rename
7.1 deletefile
usingremovefunctiondeletefile:
int remove(const char *filename);
成功deletefile时返回0, 失败时返回非零值.
7.2 renamefile
usingrenamefunctionrenamefile:
int rename(const char *oldname, const char *newname);
成功renamefile时返回0, 失败时返回非零值.
#include <stdio.h>
int main() {
// renamefile
if (rename("old.txt", "new.txt") == 0) {
printf("filerename成功\n");
} else {
perror("filerename失败");
}
// deletefile
if (remove("test.txt") == 0) {
printf("filedelete成功\n");
} else {
perror("filedelete失败");
}
return 0;
}
实践case: 学生informationmanagementsystem (fileversion)
writing一个C程序, usingfilestore学生information, implementation添加学生information, 显示学生information, find学生information and 保存学生information to file functions.
requirementsanalysis
- store many 个学生 information (姓名, 年龄, 成绩)
- 添加学生information
- 显示所 has 学生information
- 根据姓名find学生information
- 保存学生information to file
- from file加载学生information
referencecode
#include <stdio.h>
#include <string.h>
// 声明学生structure体
typedef struct {
char name[50];
int age;
float score;
} Student;
// function声明
void addStudent(Student students[], int *count);
void displayStudents(Student students[], int count);
void searchStudent(Student students[], int count);
void saveStudents(Student students[], int count, const char *filename);
void loadStudents(Student students[], int *count, const char *filename);
int main() {
Student students[50]; // 最 many store50个学生
int count = 0; // 当 before 学生数量
int choice;
// from file加载学生information
loadStudents(students, &count, "students.dat");
do {
printf("\n学生informationmanagementsystem\n");
printf("1. 添加学生information\n");
printf("2. 显示所 has 学生information\n");
printf("3. find学生information\n");
printf("4. 保存学生information to file\n");
printf("5. 退出\n");
printf("请选择operation: ");
scanf("%d", &choice);
switch (choice) {
case 1:
addStudent(students, &count);
break;
case 2:
displayStudents(students, count);
break;
case 3:
searchStudent(students, count);
break;
case 4:
saveStudents(students, count, "students.dat");
break;
case 5:
// 退出 before 保存学生information
saveStudents(students, count, "students.dat");
printf("退出system\n");
break;
default:
printf("无效选择, 请重 new 输入\n");
}
} while (choice != 5);
return 0;
}
// 添加学生information
void addStudent(Student students[], int *count) {
if (*count >= 50) {
printf("学生数量已达 on 限\n");
return;
}
printf("请输入学生information:\n");
printf("姓名: ");
scanf("%s", students[*count].name);
printf("年龄: ");
scanf("%d", &students[*count].age);
printf("成绩: ");
scanf("%f", &students[*count].score);
(*count)++;
printf("添加成功\n");
}
// 显示所 has 学生information
void displayStudents(Student students[], int count) {
if (count == 0) {
printf("暂无学生information\n");
return;
}
printf("所 has 学生information:\n");
printf("--------------------------------------------------\n");
printf("姓名\t\t年龄\t成绩\n");
printf("--------------------------------------------------\n");
for (int i = 0; i < count; i++) {
printf("%s\t\t%d\t%.1f\n",
students[i].name, students[i].age, students[i].score);
}
printf("--------------------------------------------------\n");
}
// 根据姓名find学生information
void searchStudent(Student students[], int count) {
if (count == 0) {
printf("暂无学生information\n");
return;
}
char name[50];
printf("请输入要find 学生姓名: ");
scanf("%s", name);
int found = 0;
for (int i = 0; i < count; i++) {
if (strcmp(students[i].name, name) == 0) {
printf("找 to 学生information:\n");
printf("姓名: %s\n", students[i].name);
printf("年龄: %d\n", students[i].age);
printf("成绩: %.1f\n", students[i].score);
found = 1;
break;
}
}
if (!found) {
printf("未找 to 该学生information\n");
}
}
// 保存学生information to file
void saveStudents(Student students[], int count, const char *filename) {
FILE *fp;
// 打开file
fp = fopen(filename, "wb");
if (fp == NULL) {
printf("file打开失败\n");
return;
}
// 写入学生数量
fwrite(&count, sizeof(int), 1, fp);
// 写入学生information
if (count > 0) {
fwrite(students, sizeof(Student), count, fp);
}
// 关闭file
fclose(fp);
printf("学生information保存成功\n");
}
// from file加载学生information
void loadStudents(Student students[], int *count, const char *filename) {
FILE *fp;
// 打开file
fp = fopen(filename, "rb");
if (fp == NULL) {
printf("file打开失败, using空list\n");
*count = 0;
return;
}
// 读取学生数量
fread(count, sizeof(int), 1, fp);
// 读取学生information
if (*count > 0) {
fread(students, sizeof(Student), *count, fp);
}
// 关闭file
fclose(fp);
printf("学生information加载成功, 共 %d 个学生\n", *count);
}
互动练习
练习1: writing一个C程序, from 键盘输入一些文本, 将其写入 to 一个文本filein, 然 after 再 from 该filein读取 in 容并显示 in 屏幕 on .
提示: usingfgetsfunction from 键盘输入文本, usingfputsfunction写入file, 然 after usingfgetsfunction读取file in 容并显示.
练习2: writing一个C程序, statistics一个文本filein单词 数量.
提示: usingfscanffunction读取filein 单词, 直 to 遇 to EOF.
练习3: writing一个C程序, 将一个文本file in 容copy to 另一个文本filein.
提示: usinggetcfunction from sourcesfile读取字符, usingputcfunction将字符写入 to 目标filein.