对于文件的定位,可以通过 rewind、fseek 与 ftell 函数来完成。
其中,rewind 函数用于将文件内部的位置指针重新指向一个流(数据流或者文件)的起始位置。这里需要注意的是,这里的“指针”表示的不是文件指针,而是文件内部的位置指针。即随着对文件的读写,文件的位置指针(指向当前读写字节)向后移动。而文件指针指向整个文件,如果不重新赋值,文件指针不会发生改变。
rewind 函数的一般原型如下所示:
void rewind(FILE *fp);
从上面的函数原型可以看出,rewind 并没有返回值,因此也无法做安全性检查。如下面的示例代码所示:
FILE *fp=NULL; fp=fopen("Test.txt","r"); if(fp==NULL) { } rewind(fp);
在上面的示例代码中,由于 rewind 函数没有返回值,所以我们很难判断“rewind(fp)”是否执行成功。因此,应该尽量使用 fseek 来替换 rewind 函数,从而以验证流已经成功地回绕。如下面的示例代码所示:
if (fseek(fp, 0L, SEEK_SET) != 0) { }
相对于 rewind 函数而言,fseek 函数的功能更加强大,它用来设定文件的当前读写位置,从而可以实现以任意顺序访问文件的不同位置,以实现文件的随机访问。其函数的一般原型如下所示:
int fseek(FILE *fp,long offset,int from);
如果该函数执行成功,fp 将指向以 from 为基准,偏移 offset 个字节的位置,函数的返回值为 0;如果该函数执行失败(比如 offset 超过文件自身大小),则不改变 fp 指向的位置,函数的返回值为 -1,并设置 errno 的值,可以用 perror 函数来输出错误信息。
对于 fseek 函数中的参数:第一个参数 fp 为文件指针;第二个参数 offset 为偏移量,它表示要移动的字节数,整数表示正向偏移,负数表示负向偏移;第三个参数 from 表示设定从文件的哪里开始偏移,取值范围如表 1 所示。
起始点 | 表不符号 | 数字表示 |
---|---|---|
文件首 | SEEK_SET | 0 |
当前位置 | SEEK_CUR | 1 |
文件末尾 | SEEK_END | 2 |
由表 1 可知:
- SEEK_SET 表示从文件起始位置增加 offset 个偏移量为新的读写位置;
- SEEK_CUR 表示从目前的读写位置增加 offset 个偏移量为新的读写位置;
- SEEK_END 表示将读写位置指向文件尾后,再增加 offset 个偏移量为新的读写位置。
当 from 值为 SEEK_CUR 或 SEEK_END 时,参数 offset 允许出现负值。如下面的示例代码所示:
/*将读写位置移动到离文件开头100字节处*/ fseek(fp,100L,0); /*将读写位置移动到离文件当前位置100字节处*/ fseek(fp,100L,1); /*将读写位置退回到离文件结尾100字节处*/ fseek(fp,-100L,2); /*将读写位置移动到文件的起始位置*/ fseek(fp,0L,SEEK_SET); /*将读写位置移动到文件尾*/ fseek(fp,0L,SEEK_END);
不难发现,上面的语句“(void)fseek(fp,0L,SEEK_SET);”的作用实际上等同于 rewind 函数。与此同时,在使用 fseek 函数时,还应该注意如下 3 点。
- 首先,调用 fseek 函数的文件指针 fp 应该指向已经打开的文件,否则将会出现错误。
- 其次,fseek 函数一般用于二进制文件,当然也可以用于文本文件。需要特别注意的是,当 fseek 函数用于文本文件操作时,一定要注意回车换行的情况。因为在一般浏览工具(如 UltraEdit)中,回车换行被视为两个字符 0x0D 和 0x0A,但真实的文件读写和定位却按照一个字符 0x0A 进行处理。因此,在碰到此类问题时,可以考虑将文件整个读入内存,然后在内存中手工插入 0x0D的方法,这样可以达到较好的处理效果。
- 最后,fseek 函数只返回执行的结果是否成功,并不返回文件的读写位置。因此,你可以使用 ftell 函数来取得当前文件的读写位置。
ftell 函数的原型为:
long ftell(FILE *fp);
该函数用于得到文件位置指针当前位置相对于文件首的偏移字节数。在随机方式存取文件时,由于文件位置频繁前后移动,程序不容易确定文件的当前位置。在使用 fseek 函数后,再调用函数 ftell 就能非常容易地确定文件的当前位置。如下面的示例代码所示:
long getfilelength(FILE *fp) { long curpos=0L; long length=0L; curpos = ftell(fp); fseek(fp, 0L, SEEK_END); length = ftell(fp); fseek(fp, curpos, SEEK_SET); return length; }
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/21636.html