mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
462 字
1 分钟
c06
2025-11-13
c

文件的其他相关操作#

读写指针控制#

在C 语言中,文件的读写指针(文件位置指针)用于跟踪文件中的当前位置,决定了下一次读写操作的位置

FILE* fp;

文件打开模式与初始指针位置#

模式描述初始指针位置
r只读文件开头
w只写(清空原内容)文件开头
a追加文件末尾
r+读写文件开头
w+读写 (清空原内容)文件开头
a+读写(追加)文件末尾

文件指针定位置函数#

设置文件位置;

int fseek(FILE *stream, long offset, int whence);

whence 参数:

  • SEEK_SET - 从文件开头开始
  • SEEK_CUR - 从当前位置开始
  • SEEK_END - 从文件末尾开始

实例:

#include <stdio.h>
int main() {
FILE *fp = fopen("example.txt", "r+");
if (fp == NULL) {
perror("文件打开失败");
return 1;
}
// 移动到文件开头后第10个字节
fseek(fp, 10, SEEK_SET);
// 从当前位置向前移动5个字节
fseek(fp, 5, SEEK_CUR);
// 移动到文件末尾前20个字节
fseek(fp, -20, SEEK_END);
fclose(fp);
return 0;
}

获取当前文件位置

long ftell(FILE *stream);

实例:

#include <stdio.h>
int main() {
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {
perror("文件打开失败");
return 1;
}
// 读取一些数据后获取当前位置
char buffer[100];
fread(buffer, 1, 50, fp);
long position = ftell(fp);
printf("当前文件位置: %ld\n", position);
fclose(fp);
return 0;
}

重置文件指针到开头

void rewind(FILE *stream);

实例:

#include <stdio.h>
int main() {
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {
perror("文件打开失败");
return 1;
}
// 读取文件内容
char buffer[100];
fread(buffer, 1, 100, fp);
// 重置指针到开头,重新读取
rewind(fp);
fread(buffer, 1, 100, fp);
fclose(fp);
return 0;
}

结构体io和优化#

当出现对于结构体的存储问题。我们可以使用 文件的二进制读写,来将结构体这一数据结构进行存储

有如下结构体

typedef struct _record
{
char name[128]
int age;
} record;

我们可以编写如下写入和读取的函数

// 写入文件s
int writeRecord(FILE* fp)
{
record r = { 0 };
while(1)
{
printf("Please Input the age:\n");
scanf_s("%d", &r.age);
if(r.age == 0) {
break;
}
printf("Please Input the name:\n");
scanf_s("%s", &r.name, MAXLEN);
fwrite(&r, sizeof(r), 1, fp);
}
return 0;
}
// 读取文件
int readRecord(FILE* fp)
{
while(!feof(fp))
{
record r = { 0 };
int count = fread(&r, sizeof(r), 1, fp);
if(count == 0) {
break;
}
printf("age:%d, name:%s \n", r.age, r.name);
}
return 0;
}

直接将程序以二进制形式存储

有如下主程序 和如下输入

int main(void)
{
char* filePath = ".\\struct_bin.dat";
FILE* fp = NULL;
errno_t err = fopen_s(&fp, filePath, "wb");
if(err != 0 || fp == NULL) {
return -1;
}
writeRecord(fp);
fclose(fp);
fp = NULL;
err = fopen_s(&fp, filePath, "rb");
if(err != 0 || fp == NULL) {
return -1;
}
readRecord(fp);
fclose(fp);
return 0;
}
18
XiaoMing
17
XiaoMei
19
ZhangSan
0

可以发现成功实现了程序的读写,但是通过观察生成的文件 struct_bin.dat 发现 dat

文件中有大量的 00 空白区,分析发现是结构体中的 name 有128字节的空间,其中大量的字节没有使用造成的浪费 所以我们可以 尝试改变结构体的存储方式,改为 名字长度 + 名字 + 年龄 的形式 比如8XiaoMing18

所以修改读取文件为如下代码

int optwriteRecord(FILE* fp)
{
while(1) {
record r = { 0 };
printf("Please Input the age:\n");
scanf_s("%d", &r.age);
if(r.age == 0) {
break;
}
printf("Please Input the age:\n");
scanf_s("%s", &r.name, MAXLEN);
size_t len = strlen(r.name);
fwrite(&len, sizeof(len), 1, fp);
fwrite(r.name, len, 1, fp);
fwrite(&r.age, sizeof(r.age), 1, fp);
}
return 0;
}
int optreadRecord(FILE* fp)
{
while(!feof(fp)) {
record r = { 0 };
int len = 0;
int cnt = fread(&len, sizeof(len), 1, fp);
if(cnt == 0) {
break;
}
fread(r.name, len, 1, fp);
fread(&r.age, sizeof(r.age), 1, fp);
printf("age:%d, name:%s \n", r.age, r.name);
}
return 0;
}

优化后的 struct_bin.dat 文件结构如图 dat2

明显发现占用空间减小

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

c06
https://yoyolp.github.io/posts/c_asm/c06/
作者
超级玉米人
发布于
2025-11-13
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录