目录
四、有关文件的随机读写函数
4.1 fseek
4.2 ftell
4.3 rewind
五、判定文件读取结束的标准与读写文件中途发生错误的解决办法
5.1 判定文件读取结束的标准
5.2 函数ferror与feof
5.2.1 函数ferror
5.2.2 函数feof
在上一章中,我们主要介绍了文件类型指针,如何打开与关闭文件,什么是流与标准流,以及提到的部分顺序读写函数。
C语言| 文件操作详解 (一)
这篇文章为上篇文章的续,将对有关文件随机读写的函数 fseek、ftell 、rewind 进行介绍,并解释判定文件读取结束的标准与读写文件中途发生错误的解决办法。
四、有关文件的随机读写函数
4.1 fseek
介绍:该函数主要用于改变文件中光标(就是我们打字的时候一闪一闪的小竖线)的位置,(这里说光标是为了便于理解,实际上是文件指针),再利用相关函数输入内容后,新内容会覆盖在该位置上的原内容。
例如,在打开的某个文件中有以下内容:“abcdef”,其中光标在‘c’之后(即相对于文件起始光标位置,偏移量为3),此时利用fputc在文件上打印一个字母m,则文件内容最终变为“abcmef”。
函数声明:
int fseek ( FILE* stream,long int offset,int origin );
参数:
(1) 指向标识输入流的FILE对象的指针;
(2) 要从源偏移的字节数,即偏移量;
(3) 偏移量所参考的起始位置,即源的值;
对于参数(3),源的位置值,我们一般填入下表中三个常量的一个。
常量 | 参考位置 |
SEEK_SET | 文件开头 |
SEEK_CUR | 文件指针的当前位置 |
SEEK_END | 文件末尾 |
返回值:
成功则返回0,否则返回非0值;如果发生读取或写入错误,则会设置错误指示符。
使用示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{ FILE* pf = fopen("233.txt", "w");fputs("There has a boy", pf);fseek(pf, 12, SEEK_SET);fputc('g', pf);fputc('i', pf);fputc('r', pf);fputc('l', pf);fclose(pf);return 0;
}
4.2 ftell
介绍:该函数用于返回文件指针相对于起始位置的偏移量。
函数声明:
long int ftell ( FILE * stream ) ;
参数:
指向标识流的FILE对象的指针
返回值:
成功则返回相对于文件指针初始位置的偏移量,失败则返回-1L;
使用示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{ FILE* pf = fopen("example.txt", "rb");long long size = 0;if (pf == NULL)perror("Error opening file");else {fseek(pf, 0, SEEK_END);size = ftell(pf);fclose(pf);printf("该文件的大小为%ld字节\n",size);}return 0;
}
PS:
顺便解释一下为什么上述代码可以检测文件的字节大小,因为一个字符占一个偏移量,只要得到文件末尾相对于文件初始位置的偏移量 ,就可以得到文件的字符数,而一个字符占一个字节(char型),所以可以得到文件的字节大小。
4.3 rewind
介绍:该函数用于将文件指针的位置重置为文件的起始位置
函数声明:
void rewind ( FILE * stream ) ;
参数:
指向标识流的FILE对象的指针
返回值:
无
使用示例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{ FILE* pf = fopen("123456.txt", "w+");char arr[100];fputs("fufu is very cute!", pf);rewind(pf);fgets(arr,sizeof(arr)/sizeof(arr[0]), pf);printf("%s",arr);fclose(pf);return 0;
}
五、判定文件读取结束的标准与读写文件中途发生错误的解决办法
5.1 判定文件读取结束的标准
如何判断文件读取结束?其实是一个很简单的问题。
一般来说,我们使用的有关文件读取的函数,对于文本文件,如果它的返回值是EOF(例如fgetc),或者NULL(例如fgets),则代表文件内容读取结束。
而如果是二进制文件,则是看返回值是否小于实际要读取的个数(例如fread)
5.2 函数ferror与feof
但有些时候,文件会因为各种各样的代码问题导致文件中途读写失败,如何得知哪个函数出现问题,又如何判断文件是否因为到达文件尾而读取结束?接下来我们介绍两个函数,它们可以解决我们的疑问。
5.2.1 函数ferror
函数声明:
int ferror( FILE* stream );
函数参数:
指向标识流FILE对象的指针
返回值:
如果设置了与流关联的错误指示器,则返回非零值,否则返回0
解释:
在上篇文章与这篇文章中我们介绍的函数,绝大多数遇到错误,都会设置错误指示器,如果在每一个有关文件读写的函数后面都加一个if利用ferror进行判断,就可以知道在哪里出了问题。
例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{FILE* pf;pf = fopen("myfile.txt", "r+");//注释if (pf == NULL) perror("Error opening file");else {char a=fgetc(pf);if (ferror(pf)) {printf("Error Reading to myfile.txt\n");exit(3);}fputc('x', pf);if (ferror(pf)) {printf("Error Writing to myfile.txt\n");exit(2);} fclose(pf);}return 0;
}
我们先将代码复制到工程中,然后在工程文件的目录下创建名为“myfile”的txt类型文件,并输入如下内容:
1.如果将注释一行的“r+”更改为“r”,运行程序,结果为:
2. 如果将注释一行的“r+”更改为“w”,运行程序,结果为:
根据ferror函数与运行结果, 我们就可以锁定问题出现在文件的读写方式上。
3. 如果不进行更改,运行程序,结果为:
5.2.2 函数feof
函数声明:
int feof ( FILE* stream);
参数:
指向标识流的FILE对象的指针
返回值:
如果设置了与流关联的文件结束指示器,则返回非零值,否则,返回0
解释:
如果正常到达文件末尾而结束读取,则会返回非0值,如果未到达文件末尾而结束读取,则会返回0,用于检查程序是否读取完整。
注意:
feof是用于判断文件读取结束的原因是否是到达文件末尾,千万不可在文件读取过程中使用feof!
例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>int main ()
{FILE * pFile;int n = 0;pFile = fopen ("myfile.txt","rb");if (pFile==NULL) perror ("Error opening file");else{while (fgetc(pFile) != EOF) {++n;}if (feof(pFile)) {puts ("End-of-File reached.");printf ("Total number of bytes read: %d\n", n);}else puts ("End-of-File was not reached.");fclose (pFile);}return 0;
}
此代码作用为:
打开名为“myfile.txt”的文件,并通过逐个读取所有字符来计算文件的字节数。该程序检查是否已到达文件末尾,如果已到达,则打印读取的总字节数。
小伙伴们可以自己试一下,我这里就不演示了。
本文完!