文件随机读写是C语言中灵活访问文件内容的重要方式。东巴文(db-w.cn) 将带你深入理解文件随机读写的原理与实践。
💡 东巴文观点:随机读写让你能够灵活地访问文件的任意位置,是处理复杂数据文件的关键技能。
#include <stdio.h>
void randomIODefinition() {
printf("=== 东巴文随机读写的定义 ===\n\n");
printf("随机读写(Random I/O):\n");
printf(" 可以在文件的任意位置进行读写\n");
printf(" 通过文件位置指针控制访问位置\n");
printf(" 适合处理结构化数据文件\n\n");
printf("随机读写特点:\n");
printf(" 1. 灵活性高\n");
printf(" 2. 效率较高\n");
printf(" 3. 适合随机访问\n");
printf(" 4. 需要手动管理位置\n");
printf("\n随机读写函数:\n");
printf(" fseek - 设置文件位置\n");
printf(" ftell - 获取文件位置\n");
printf(" rewind - 重置文件位置\n");
printf(" fgetpos - 获取文件位置\n");
printf(" fsetpos - 设置文件位置\n");
}
int main() {
randomIODefinition();
return 0;
}
#include <stdio.h>
void filePositionPointer() {
printf("=== 东巴文文件位置指针 ===\n\n");
printf("文件位置指针:\n");
printf(" 指向文件当前读写位置的指针\n");
printf(" 每次读写后自动移动\n");
printf(" 可以手动调整位置\n\n");
printf("位置指针特性:\n");
printf(" 1. 从文件开头计算(0开始)\n");
printf(" 2. 每次读写后自动更新\n");
printf(" 3. 可以获取当前位置\n");
printf(" 4. 可以设置任意位置\n");
printf("\n位置指针操作:\n");
printf(" 读取:位置指针后移\n");
printf(" 写入:位置指针后移\n");
printf(" 定位:位置指针跳转\n");
printf(" 查询:获取当前位置\n");
}
int main() {
filePositionPointer();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void fseekFunction() {
printf("=== 东巴文fseek函数 ===\n\n");
printf("函数原型:\n");
printf(" int fseek(FILE* stream, long offset, int whence);\n\n");
printf("功能:\n");
printf(" 设置文件位置指针\n\n");
printf("参数:\n");
printf(" stream - 文件指针\n");
printf(" offset - 偏移量\n");
printf(" whence - 起始位置\n\n");
printf("whence参数:\n");
printf(" SEEK_SET (0) - 文件开头\n");
printf(" SEEK_CUR (1) - 当前位置\n");
printf(" SEEK_END (2) - 文件末尾\n\n");
printf("返回值:\n");
printf(" 成功:0\n");
printf(" 失败:-1\n");
// 示例:创建测试文件
FILE *fp = fopen("test.txt", "w+");
if (fp == NULL) {
perror("打开文件失败");
return;
}
// 写入数据
fprintf(fp, "0123456789ABCDEFGHIJ");
// 定位到第5个字节
fseek(fp, 5, SEEK_SET);
char ch = fgetc(fp);
printf("\n第5个字节:%c\n", ch);
// 定位到倒数第5个字节
fseek(fp, -5, SEEK_END);
ch = fgetc(fp);
printf("倒数第5个字节:%c\n", ch);
// 从当前位置后移3个字节
fseek(fp, 3, SEEK_CUR);
ch = fgetc(fp);
printf("当前位置后移3个字节:%c\n", ch);
fclose(fp);
}
int main() {
fseekFunction();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void ftellFunction() {
printf("=== 东巴文ftell函数 ===\n\n");
printf("函数原型:\n");
printf(" long ftell(FILE* stream);\n\n");
printf("功能:\n");
printf(" 获取当前文件位置\n\n");
printf("参数:\n");
printf(" stream - 文件指针\n\n");
printf("返回值:\n");
printf(" 成功:当前位置(相对于文件开头)\n");
printf(" 失败:-1L\n");
// 示例
FILE *fp = fopen("test.txt", "w+");
if (fp == NULL) {
perror("打开文件失败");
return;
}
fprintf(fp, "东巴文db-w.cn");
// 获取当前位置
long pos = ftell(fp);
printf("\n当前位置:%ld\n", pos);
// 定位到开头
fseek(fp, 0, SEEK_SET);
pos = ftell(fp);
printf("定位到开头后:%ld\n", pos);
// 读取一个字符
fgetc(fp);
pos = ftell(fp);
printf("读取一个字符后:%ld\n", pos);
fclose(fp);
printf("\n应用场景:\n");
printf(" 1. 获取文件大小\n");
printf(" 2. 记录读写位置\n");
printf(" 3. 计算相对位置\n");
printf(" 4. 实现断点续传\n");
}
int main() {
ftellFunction();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void rewindFunction() {
printf("=== 东巴文rewind函数 ===\n\n");
printf("函数原型:\n");
printf(" void rewind(FILE* stream);\n\n");
printf("功能:\n");
printf(" 将文件位置指针重置到文件开头\n");
printf(" 清除错误标志和EOF标志\n\n");
printf("参数:\n");
printf(" stream - 文件指针\n\n");
printf("等价于:\n");
printf(" fseek(fp, 0L, SEEK_SET);\n");
printf(" clearerr(fp);\n");
// 示例
FILE *fp = fopen("test.txt", "w+");
if (fp == NULL) {
perror("打开文件失败");
return;
}
fprintf(fp, "东巴文\n第二行\n第三行\n");
// 读取一遍
printf("第一次读取:\n");
rewind(fp);
char buffer[100];
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf(" %s", buffer);
}
// 重置后再读取
printf("\n第二次读取:\n");
rewind(fp);
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf(" %s", buffer);
}
fclose(fp);
printf("\n应用场景:\n");
printf(" 1. 重新读取文件\n");
printf(" 2. 多次处理文件\n");
printf(" 3. 清除错误状态\n");
}
int main() {
rewindFunction();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void fgetposFsetpos() {
printf("=== 东巴文fgetpos和fsetpos函数 ===\n\n");
printf("fgetpos函数原型:\n");
printf(" int fgetpos(FILE* stream, fpos_t* pos);\n\n");
printf("fsetpos函数原型:\n");
printf(" int fsetpos(FILE* stream, const fpos_t* pos);\n\n");
printf("功能:\n");
printf(" fgetpos - 获取文件位置\n");
printf(" fsetpos - 设置文件位置\n\n");
printf("优势:\n");
printf(" 1. 支持大文件(>2GB)\n");
printf(" 2. 可移植性好\n");
printf(" 3. 类型安全\n");
// 示例
FILE *fp = fopen("test.txt", "w+");
if (fp == NULL) {
perror("打开文件失败");
return;
}
fprintf(fp, "东巴文db-w.cn");
// 保存位置
fpos_t pos;
fgetpos(fp, &pos);
printf("\n保存当前位置\n");
// 移动位置
fseek(fp, 0, SEEK_SET);
printf("移动到开头\n");
// 恢复位置
fsetpos(fp, &pos);
printf("恢复位置\n");
printf("当前位置:%ld\n", ftell(fp));
fclose(fp);
printf("\n使用建议:\n");
printf(" 1. 大文件使用fgetpos/fsetpos\n");
printf(" 2. 小文件使用ftell/fseek\n");
printf(" 3. 需要保存位置时使用\n");
}
int main() {
fgetposFsetpos();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
long getFileSize(const char *filename) {
FILE *fp = fopen(filename, "rb");
if (fp == NULL) {
return -1;
}
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fclose(fp);
return size;
}
void getFileSizeExample() {
printf("=== 东巴文获取文件大小 ===\n\n");
// 创建测试文件
FILE *fp = fopen("test.txt", "w");
if (fp != NULL) {
fprintf(fp, "东巴文db-w.cn\n");
fprintf(fp, "文件大小测试\n");
fclose(fp);
}
// 获取文件大小
long size = getFileSize("test.txt");
if (size >= 0) {
printf("文件大小:%ld 字节\n", size);
} else {
printf("获取文件大小失败\n");
}
printf("\n获取文件大小步骤:\n");
printf(" 1. 打开文件\n");
printf(" 2. 定位到文件末尾\n");
printf(" 3. 获取当前位置\n");
printf(" 4. 关闭文件\n");
}
int main() {
getFileSizeExample();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void readAtPosition() {
printf("=== 东巴文读取文件指定位置 ===\n\n");
// 创建测试文件
FILE *fp = fopen("data.txt", "w+");
if (fp == NULL) {
perror("打开文件失败");
return;
}
// 写入数据
for (int i = 0; i < 10; i++) {
fprintf(fp, "数据%02d\n", i);
}
// 读取第5行
fseek(fp, 0, SEEK_SET);
char buffer[100];
for (int i = 0; i < 5; i++) {
if (fgets(buffer, sizeof(buffer), fp) == NULL) {
break;
}
}
printf("第5行:%s", buffer);
// 读取最后一行
fseek(fp, -20, SEEK_END); // 假设每行约20字节
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
// 读取到最后一行
}
printf("最后一行:%s", buffer);
fclose(fp);
printf("\n随机读取应用:\n");
printf(" 1. 读取特定记录\n");
printf(" 2. 跳过部分内容\n");
printf(" 3. 实现分页显示\n");
printf(" 4. 数据库查询\n");
}
int main() {
readAtPosition();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void modifyFileContent() {
printf("=== 东巴文修改文件内容 ===\n\n");
// 创建测试文件
FILE *fp = fopen("modify.txt", "w+");
if (fp == NULL) {
perror("打开文件失败");
return;
}
// 写入初始内容
fprintf(fp, "原始内容第一行\n");
fprintf(fp, "原始内容第二行\n");
fprintf(fp, "原始内容第三行\n");
// 定位到第二行开头
fseek(fp, 0, SEEK_SET);
char buffer[100];
fgets(buffer, sizeof(buffer), fp); // 跳过第一行
// 记录第二行位置
long pos = ftell(fp);
// 读取第二行
fgets(buffer, sizeof(buffer), fp);
printf("原始第二行:%s", buffer);
// 修改第二行
fseek(fp, pos, SEEK_SET);
fprintf(fp, "修改后的第二行\n");
// 读取验证
fseek(fp, 0, SEEK_SET);
printf("\n修改后的文件内容:\n");
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf(" %s", buffer);
}
fclose(fp);
printf("\n修改文件注意事项:\n");
printf(" 1. 新内容长度要匹配\n");
printf(" 2. 注意文件位置\n");
printf(" 3. 及时刷新缓冲区\n");
printf(" 4. 备份重要文件\n");
}
int main() {
modifyFileContent();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int id;
char name[50];
int age;
float score;
} Student;
void structuredDataAccess() {
printf("=== 东巴文结构化数据随机访问 ===\n\n");
// 创建学生数据文件
FILE *fp = fopen("students.dat", "wb+");
if (fp == NULL) {
perror("打开文件失败");
return;
}
// 写入学生数据
Student students[5] = {
{1, "东巴文", 20, 95.5f},
{2, "张三", 21, 88.0f},
{3, "李四", 22, 92.5f},
{4, "王五", 20, 85.0f},
{5, "赵六", 21, 90.0f}
};
fwrite(students, sizeof(Student), 5, fp);
// 随机访问第3个学生
Student student;
fseek(fp, 2 * sizeof(Student), SEEK_SET);
fread(&student, sizeof(Student), 1, fp);
printf("第3个学生:\n");
printf(" ID:%d\n", student.id);
printf(" 姓名:%s\n", student.name);
printf(" 年龄:%d\n", student.age);
printf(" 成绩:%.1f\n", student.score);
// 修改第3个学生
student.score = 99.0f;
fseek(fp, 2 * sizeof(Student), SEEK_SET);
fwrite(&student, sizeof(Student), 1, fp);
printf("\n修改后的第3个学生成绩:%.1f\n", student.score);
// 遍历所有学生
printf("\n所有学生:\n");
fseek(fp, 0, SEEK_SET);
while (fread(&student, sizeof(Student), 1, fp) == 1) {
printf(" %d. %s, %d岁, 成绩%.1f\n",
student.id, student.name, student.age, student.score);
}
fclose(fp);
printf("\n结构化数据访问优势:\n");
printf(" 1. 快速定位记录\n");
printf(" 2. 高效修改数据\n");
printf(" 3. 节省存储空间\n");
printf(" 4. 适合数据库应用\n");
}
int main() {
structuredDataAccess();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void usePositioningFunctions() {
printf("=== 东巴文正确使用定位函数 ===\n\n");
FILE *fp = fopen("test.txt", "w+");
if (fp == NULL) {
perror("打开文件失败");
return;
}
fprintf(fp, "东巴文db-w.cn");
// ✅ 正确:检查fseek返回值
if (fseek(fp, 0, SEEK_SET) != 0) {
perror("定位失败");
fclose(fp);
return;
}
// ✅ 正确:检查ftell返回值
long pos = ftell(fp);
if (pos == -1L) {
perror("获取位置失败");
fclose(fp);
return;
}
printf("当前位置:%ld\n", pos);
fclose(fp);
printf("\n使用建议:\n");
printf(" 1. 检查定位函数返回值\n");
printf(" 2. 注意文件打开模式\n");
printf(" 3. 避免越界访问\n");
printf(" 4. 处理大文件使用fgetpos/fsetpos\n");
}
int main() {
usePositioningFunctions();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void avoidCommonErrors() {
printf("=== 东巴文避免常见错误 ===\n\n");
printf("常见错误:\n\n");
printf("1. 忘记检查返回值:\n");
printf(" ❌ fseek(fp, 100, SEEK_SET);\n");
printf(" ✅ if (fseek(fp, 100, SEEK_SET) != 0) { /* 处理错误 */ }\n\n");
printf("2. 越界访问:\n");
printf(" ❌ fseek(fp, -100, SEEK_SET); // 负偏移\n");
printf(" ✅ 先检查文件大小\n\n");
printf("3. 模式不匹配:\n");
printf(" ❌ 用\"w\"模式打开后尝试读取\n");
printf(" ✅ 使用\"w+\"或\"r+\"模式\n\n");
printf("4. 未刷新缓冲区:\n");
printf(" ❌ 写入后立即定位读取\n");
printf(" ✅ 使用fflush或fclose刷新\n");
printf("\n避免建议:\n");
printf(" 1. 总是检查返回值\n");
printf(" 2. 验证偏移量\n");
printf(" 3. 选择正确的模式\n");
printf(" 4. 及时刷新缓冲区\n");
}
int main() {
avoidCommonErrors();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void performanceOptimization() {
printf("=== 东巴文性能优化 ===\n\n");
printf("性能优化技巧:\n\n");
printf("1. 减少定位操作:\n");
printf(" - 批量读写数据\n");
printf(" - 避免频繁定位\n");
printf(" - 使用顺序读写\n\n");
printf("2. 使用合适的缓冲区:\n");
printf(" - 设置大缓冲区\n");
printf(" - 使用setvbuf函数\n");
printf(" - 减少磁盘I/O\n\n");
printf("3. 合理的文件结构:\n");
printf(" - 固定大小记录\n");
printf(" - 索引文件\n");
printf(" - 分块存储\n\n");
printf("4. 缓存常用数据:\n");
printf(" - 内存缓存\n");
printf(" - 预读取数据\n");
printf(" - 延迟写入\n");
printf("\n优化建议:\n");
printf(" 1. 分析访问模式\n");
printf(" 2. 选择合适的策略\n");
printf(" 3. 测试性能\n");
printf(" 4. 持续优化\n");
}
int main() {
performanceOptimization();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
void errorHandling() {
printf("=== 东巴文错误处理 ===\n\n");
FILE *fp = fopen("test.txt", "w+");
if (fp == NULL) {
perror("打开文件失败");
return;
}
// 写入数据
if (fprintf(fp, "东巴文db-w.cn") < 0) {
perror("写入失败");
fclose(fp);
return;
}
// 定位操作
if (fseek(fp, 0, SEEK_SET) != 0) {
perror("定位失败");
fclose(fp);
return;
}
// 获取位置
long pos = ftell(fp);
if (pos == -1L) {
perror("获取位置失败");
fclose(fp);
return;
}
printf("当前位置:%ld\n", pos);
// 检查错误标志
if (ferror(fp)) {
perror("文件错误");
clearerr(fp);
}
fclose(fp);
printf("\n错误处理建议:\n");
printf(" 1. 检查所有操作返回值\n");
printf(" 2. 使用perror输出错误\n");
printf(" 3. 使用ferror检查错误\n");
printf(" 4. 使用clearerr清除错误\n");
}
int main() {
errorHandling();
return 0;
}
完成本章学习后,请确认:
掌握文件随机读写后,你可以继续学习:
如果遇到问题,欢迎访问 东巴文(db-w.cn) 获取帮助!
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文随机读写提示:随机读写是处理复杂数据文件的关键技能。在 db-w.cn,我们会通过大量实例帮你掌握文件操作!