Appearance
文件操作
文件操作是C语言程序设计中重要的内容,通过文件可以持久化存储数据。本章将详细介绍C语言的文件读写操作。
文件基础
文件的打开和关闭
c
/*
* 文件的打开和关闭
*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
/* fopen - 打开文件 */
/* 模式:
* "r" - 只读(文件必须存在)
* "w" - 只写(文件不存在则创建,存在则清空)
* "a" - 追加(文件不存在则创建)
* "r+" - 读写(文件必须存在)
* "w+" - 读写(文件不存在则创建,存在则清空)
* "a+" - 读写追加(文件不存在则创建)
* "rb", "wb", "ab" - 二进制模式
*/
/* 打开文件用于写入 */
fp = fopen("test.txt", "w");
if (fp == NULL) {
printf("无法打开文件\n");
return 1;
}
printf("文件打开成功\n");
/* 写入一些内容 */
fprintf(fp, "Hello, File!\n");
fprintf(fp, "这是第二行\n");
/* fclose - 关闭文件 */
fclose(fp);
printf("文件已关闭\n");
/* 重新打开用于读取 */
fp = fopen("test.txt", "r");
if (fp == NULL) {
printf("无法打开文件\n");
return 1;
}
/* 读取并显示内容 */
char buffer[100];
printf("\n文件内容:\n");
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("%s", buffer);
}
fclose(fp);
return 0;
}文件读写函数
c
/*
* 文件读写函数
*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
/* === 字符读写 === */
/* 写入字符 */
fp = fopen("char_test.txt", "w");
if (fp == NULL) {
perror("打开文件失败");
return 1;
}
fputc('H', fp); /* 写入单个字符 */
fputc('i', fp);
fputc('\n', fp);
fputs("Hello\n", fp); /* 写入字符串 */
fputs("World\n", fp);
fclose(fp);
/* 读取字符 */
fp = fopen("char_test.txt", "r");
if (fp != NULL) {
printf("字符读取:\n");
int ch;
while ((ch = fgetc(fp)) != EOF) { /* EOF表示文件结束 */
putchar(ch);
}
fclose(fp);
}
/* === 格式化读写 === */
fp = fopen("format_test.txt", "w");
if (fp != NULL) {
/* fprintf - 格式化写入 */
fprintf(fp, "姓名: %s\n", "张三");
fprintf(fp, "年龄: %d\n", 25);
fprintf(fp, "成绩: %.1f\n", 85.5);
fclose(fp);
}
/* fscanf - 格式化读取 */
fp = fopen("format_test.txt", "r");
if (fp != NULL) {
char name[50];
int age;
float score;
/* 跳过"姓名: " */
fscanf(fp, "姓名: %s\n", name);
fscanf(fp, "年龄: %d\n", &age);
fscanf(fp, "成绩: %f\n", &score);
printf("\n格式化读取:\n");
printf("姓名: %s\n", name);
printf("年龄: %d\n", age);
printf("成绩: %.1f\n", score);
fclose(fp);
}
return 0;
}二进制文件读写
c
/*
* 二进制文件读写
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 结构体定义 */
struct Student {
char name[50];
int age;
float score;
};
int main(void)
{
struct Student students[] = {
{"张三", 20, 85.5},
{"李四", 21, 90.0},
{"王五", 22, 78.5}
};
int count = 3;
/* 写入二进制文件 */
FILE *fp = fopen("students.dat", "wb");
if (fp == NULL) {
perror("打开文件失败");
return 1;
}
/* fwrite - 写入二进制数据 */
/* fwrite(数据地址, 每个元素大小, 元素个数, 文件指针) */
fwrite(&count, sizeof(int), 1, fp); /* 先写入记录数 */
fwrite(students, sizeof(struct Student), count, fp);
fclose(fp);
printf("已写入%d条学生记录\n", count);
/* 读取二进制文件 */
fp = fopen("students.dat", "rb");
if (fp == NULL) {
perror("打开文件失败");
return 1;
}
/* fread - 读取二进制数据 */
int read_count;
fread(&read_count, sizeof(int), 1, fp);
printf("\n读取到%d条记录:\n", read_count);
struct Student *read_students = (struct Student*)malloc(
read_count * sizeof(struct Student));
if (read_students != NULL) {
fread(read_students, sizeof(struct Student), read_count, fp);
for (int i = 0; i < read_count; i++) {
printf("学生%d: %s, %d岁, 成绩%.1f\n",
i + 1, read_students[i].name,
read_students[i].age, read_students[i].score);
}
free(read_students);
}
fclose(fp);
return 0;
}文件定位
c
/*
* 文件定位函数
*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
/* 创建测试文件 */
fp = fopen("seek_test.txt", "w");
if (fp != NULL) {
fprintf(fp, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
fclose(fp);
}
/* 打开文件进行随机访问 */
fp = fopen("seek_test.txt", "r");
if (fp == NULL) {
perror("打开文件失败");
return 1;
}
/* ftell - 获取当前位置 */
long pos = ftell(fp);
printf("当前位置: %ld\n", pos);
/* fseek - 移动文件指针 */
/* fseek(文件指针, 偏移量, 起始位置)
* SEEK_SET - 文件开头
* SEEK_CUR - 当前位置
* SEEK_END - 文件末尾
*/
/* 移动到第10个字符 */
fseek(fp, 10, SEEK_SET);
char ch = fgetc(fp);
printf("第10个字符: %c\n", ch);
/* 从当前位置移动 */
fseek(fp, 5, SEEK_CUR);
ch = fgetc(fp);
printf("当前位置+5的字符: %c\n", ch);
/* 移动到文件末尾 */
fseek(fp, 0, SEEK_END);
long file_size = ftell(fp);
printf("文件大小: %ld 字节\n", file_size);
/* 从末尾向前移动 */
fseek(fp, -5, SEEK_END);
printf("最后5个字符: ");
for (int i = 0; i < 5; i++) {
putchar(fgetc(fp));
}
printf("\n");
/* rewind - 回到文件开头 */
rewind(fp);
printf("\n回到开头后第一个字符: %c\n", fgetc(fp));
fclose(fp);
return 0;
}错误处理
c
/*
* 文件错误处理
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void)
{
FILE *fp;
/* 尝试打开不存在的文件 */
fp = fopen("nonexistent.txt", "r");
if (fp == NULL) {
/* perror - 打印错误信息 */
perror("打开文件失败");
/* errno - 错误码 */
printf("错误码: %d\n", errno);
/* strerror - 错误描述 */
printf("错误描述: %s\n", strerror(errno));
}
/* ferror - 检查文件错误 */
fp = fopen("error_test.txt", "w");
if (fp != NULL) {
/* 尝试从只写文件读取 */
/* int ch = fgetc(fp); */ /* 会返回EOF */
if (ferror(fp)) {
printf("文件发生错误\n");
clearerr(fp); /* 清除错误标志 */
}
fclose(fp);
}
/* feof - 检查文件结束 */
fp = fopen("error_test.txt", "r");
if (fp != NULL) {
printf("\n读取到文件末尾:\n");
while (!feof(fp)) {
int ch = fgetc(fp);
if (ch != EOF) {
putchar(ch);
}
}
if (feof(fp)) {
printf("\n已到达文件末尾\n");
}
fclose(fp);
}
/* 安全的文件操作 */
printf("\n安全的文件操作示例:\n");
fp = fopen("safe_test.txt", "w");
if (fp == NULL) {
perror("无法创建文件");
return 1;
}
if (fprintf(fp, "测试内容\n") < 0) {
perror("写入失败");
fclose(fp);
return 1;
}
if (fclose(fp) != 0) {
perror("关闭文件失败");
return 1;
}
printf("文件操作成功\n");
return 0;
}文件操作实例
复制文件
c
/*
* 文件复制
*/
#include <stdio.h>
#include <stdlib.h>
int copy_file(const char *src, const char *dest)
{
FILE *fp_src = fopen(src, "rb");
if (fp_src == NULL) {
perror("打开源文件失败");
return -1;
}
FILE *fp_dest = fopen(dest, "wb");
if (fp_dest == NULL) {
perror("创建目标文件失败");
fclose(fp_src);
return -1;
}
/* 缓冲区复制 */
char buffer[4096];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), fp_src)) > 0) {
if (fwrite(buffer, 1, bytes_read, fp_dest) != bytes_read) {
perror("写入失败");
fclose(fp_src);
fclose(fp_dest);
return -1;
}
}
fclose(fp_src);
fclose(fp_dest);
return 0;
}
int main(void)
{
/* 创建源文件 */
FILE *fp = fopen("source.txt", "w");
if (fp != NULL) {
fprintf(fp, "这是源文件的内容\n");
fprintf(fp, "第二行\n");
fprintf(fp, "第三行\n");
fclose(fp);
}
/* 复制文件 */
if (copy_file("source.txt", "destination.txt") == 0) {
printf("文件复制成功\n");
} else {
printf("文件复制失败\n");
}
return 0;
}统计文件信息
c
/*
* 统计文件信息
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
char filename[100];
printf("请输入文件名: ");
scanf("%s", filename);
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
perror("打开文件失败");
return 1;
}
int chars = 0, words = 0, lines = 0;
int in_word = 0; /* 是否在单词中 */
int ch;
while ((ch = fgetc(fp)) != EOF) {
chars++;
/* 统计行数 */
if (ch == '\n') {
lines++;
}
/* 统计单词数 */
if (isspace(ch)) {
in_word = 0;
} else if (!in_word) {
in_word = 1;
words++;
}
}
/* 如果文件不为空且不以换行结尾,行数+1 */
if (chars > 0 && ch != '\n') {
lines++;
}
printf("\n文件统计:\n");
printf("字符数: %d\n", chars);
printf("单词数: %d\n", words);
printf("行数: %d\n", lines);
fclose(fp);
return 0;
}小结
本章学习了:
- 文件打开关闭:fopen、fclose、文件模式
- 文件读写:fgetc、fputc、fgets、fputs、fprintf、fscanf
- 二进制文件:fread、fwrite
- 文件定位:fseek、ftell、rewind
- 错误处理:ferror、feof、clearerr、perror
- 文件操作实例:文件复制、文件统计
下一章,我们将学习内存管理,了解C语言的动态内存分配。
