【C语言基础】:文件操作详解(后篇)-1
https://developer.aliyun.com/article/1538344
二、文件的随机读写
2.1 fseek函数
根据文件指针的位置和偏移量来定位文件指针(文件内容的光标)。
函数原型:
int fseek ( FILE * stream, long int offset, int origin );
重新定位流位置指示器
将与流关联的位置指示器设置为新位置。
对于以二进制模式打开的流,通过将偏移量添加到由origin指定的参考位置来定义新位置。
对于以文本模式打开的流,offset值要么为零,要么为先前调用ftell返回的值,origin必须为SEEK_SET。
如果使用这些参数的其他值调用函数,则支持取决于特定的系统和库实现(不可移植)。
在成功调用此函数后,流的文件结束内部指示符将被清除,并且先前调用ungetc对该流的所有效果将被删除。
在为update(读+写)打开的流上,调用fseek允许在读和写之间切换。
参数说明如下:
stream:指向文件的指针,它指定了要设置位置指针的文件。
offset:相对于 origin 的偏移量。偏移量可以是正数(向文件末尾方向移动)或负数(向文件开头方向移动)。
origin:指定了从哪个位置计算偏移量的基准。可以取以下三个值之一:
- SEEK_SET:从文件开头计算偏移量。
- SEEK_CUR:从当前位置计算偏移量。
- SEEK_END:从文件末尾计算偏移量。
fseek 函数的返回值是一个 int 类型,表示操作是否成功。如果成功,返回0;如果出现错误,返回非零值。通过 ferror 函数可以检查是否发生了错误。
【示例】:
#include<stdio.h> int main() { // 打开文件 FILE* pf = fopen("test1.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 读文件 int ch = fgetc(pf); printf("%c\n", ch); // fseek(pf, 5, SEEK_SET);// f // fseek(pf, 4, SEEK_CUR);// f fseek(pf, -4, SEEK_END);// f ch = fgetc(pf); printf("%c\n", ch); // 关闭文件 fclose(pf); pf = NULL; return 0; }
2.2 ftell函数
返回文件指针相对于起始位置的偏移量
函数原型:
long int ftell ( FILE * stream );
获取流中的当前位置
返回流的位置指示器的当前值。
对于二进制流,这是从文件开头开始的字节数。
对于文本流,数值可能没有意义,但仍然可以用于稍后使用fseek将位置恢复到相同的位置(如果使用ungetc放回的字符仍然等待读取,则行为未定义)。
参数说明如下:
stream:指向文件的指针,它指定了要获取位置指针的文件。
ftell 函数的返回值是一个 long int 类型,表示当前位置指针相对于文件开头的偏移量(以字节为单位)。如果出现错误,返回值可能是 -1。通常情况下,返回值应该是非负数,但标准并未规定返回值的确切含义,因此应谨慎处理。
【示例】:
#include<stdio.h> int main() { // 打开文件 FILE* pf = fopen("test1.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 读文件 int ch = fgetc(pf); printf("%c\n", ch);// a fseek(pf, -4, SEEK_END);// f printf("%d\n", ftell(pf)); // 关闭文件 fclose(pf); pf = NULL; return 0; }
2.3 rewind函数
让文件指针的位置回到文件的起始位置
函数原型:
void rewind ( FILE * stream );
设置流的起始位置
将与流关联的位置指示器设置为文件的开头。
在成功调用此函数后,与流相关的文件结束和错误内部指示器将被清除,并且先前调用ungetc对该流的所有效果将被删除。
在为更新(读+写)打开的流上,对rewind的调用允许在读和写之间切换。
参数说明如下:
stream:指向文件的指针,它指定了要重置位置指针的文件。
rewind 函数没有返回值。它会将文件流的位置指针设置为文件开头,以便重新读取文件内容或进行其他操作。使用 rewind 函数后,可以再次从文件开头开始读取数据。
【示例】:
#include<stdio.h> int main() { // 打开文件 FILE* pf = fopen("test1.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 读文件 int ch = fgetc(pf); printf("%c\n", ch);// a fseek(pf, -4, SEEK_END); ch = fgetc(pf); printf("%c\n", ch);// f rewind(pf); ch = fgetc(pf); printf("%c\n", ch);// a // 关闭文件 fclose(pf); pf = NULL; return 0; }
三、文件读取结束的判定
3.1 feof函数
函数原型:
int feof ( FILE * stream );
当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束。
【示例】:
#include<stdio.h> int main() { // 打开文件 FILE* pf = fopen("test1.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 读文件 int ch = 0; while ((ch = fgetc(pf)) != EOF) { printf("%c\n", ch); } // 导致读取结束的原因 if (feof(pf)) { printf("遇到文件末尾,正常结束"); } else if (ferror(pf)) { perror("fgetc"); } // 关闭文件 fclose(pf); pf = NULL; return 0; }
四、文件缓冲区
ANSIC 标准采用“缓冲文件系统” 处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟⼀块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题。