fseek()函数可以像对待一个数组一样对待一个文件,fopen()打开的文件中,fseek()可以直接移动到任意字节的位置。
如果按反序显示一个文件,,且使用命令行参数获得要读取的文件的名字。(注:fseek()接受3个参数,返回一个int值),ftell()以一个long类型值返回一个文件的当前位置。
/*reverse.c 按反序显示一个文件*/
#include <stdio.h>
#include <stdlib.h>
#define CNTL_Z '\032' /*DOS文本文件中的文件结尾标记*/
#define SLEN 50
int main (void)
{
char file[SLEN];
char ch;
FILE *fp;
long count,last;
puts("Enter tne name of the file to be processed:");
gets(file);
if ((fp=fopen(file,"rb"))==NULL){ /*只读和二进制模式,适用于二进制模式,但不一定适用于文本模式*/
printf("resever can't open %s\n",file);
exit(1);
}
fseek(fp,0L,SEEK_END); /*定位到文件结尾处*/
last=ftell(fp); /*把从文件开始到文件结束的字节数目赋给last*/
for(count=1L;count<=last;count++){
fseek(fp,-count,SEEK_END); /*回退,第一次循环将程序定位到文件结尾前的第一个字符,就是文件的最后一个字符,依次往前,一直到文件的第一个字符*/
ch=getc(fp);
/*针对DOS,UNIX下也可以工作*/
if(ch!=CNTL_Z && ch != '\r') /*防止程序打印“Ctrl+Z”字符*/
putchar(ch);
/*针对Macintosh*/
/*if(ch == '\r')
putchar('\n');
else
putchar(ch); */
}
putchar('\n');
fclose(fp);
return 0;
}
fseek()的工作方式
int fseek ( FILE * stream, long int offset, int origin );
模式 | 偏移量的起始点 |
SEEK_SET | 文件开始 |
SEEK_CUR | 当前位置 |
SEEK_END | 文件结尾 |
比如,fp作为一个文件指针,
fseek(fp,0L,SEEK_SET); //找到文件的开始处
fseek(fp,10L,SEEK_SET); //找到文件的第10个字节
fseek(fp,2L,SEEK_CUR); //从文件的当前位置向前移动2个字节
fseek(fp,0L,SEEK_END); //到达文件的结尾处
fseek(fp,-10L,SEEK_END); //从文件结尾处退回10个字节
如果正常,fseek()返回0;如果有错误,比如试图移动超过文件范围,fseek()返回-1.
ftell()函数为long类型,返回文件的当前位置。在ANSI下,ftell()函数在stdio.h头文件的中被声明.ftell()函数通过返回距离文件开始处的字节数来确定文件的位置,比如文件的第一个字节到文件的开始处的距离就是0,适用于二进制模式,但不一定适用于文本模式
1.二进制模式和文本模式
UNIX只有一种文件格式,上述程序可以无需改动(UNIX文件中通常不包含Ctrl+Z和\r)。而MS-DOS值得关注,许多MS-DOS编辑器使用Ctrl+Z标识文本文件的结尾,如果以文本文件的形式打开,并无大碍;如果以二进制模式打开,Ctrl+Z会被看做字符。而真正的文件在后面,除非紧跟着Ctrl+Z,否则是用空字符填满到256(或其他数)的倍数。DOS下不打印空字符。
2.MS-DOS用\r\n组合表示文本文件的换行符,以文本模式打开文件的C程序将\r\n看做\n。二进制模式中要向上述程序中处理\r。
由于ftell()在文本模式和二进制模式下的工作方式有所不同,ANSI C规定,对于文本模式,ftell()返回一个可以用作fseek()的第二个参数的值。例如,MS-DOS中,ftell()返回一个将\r\n看做一个字符的计数值。
在文本模式中,确保有效的fseek()调用只有以下这些
fseek(file,0L,SEEK_SET) | 到文件开始 |
fseek(file,0L,SEEK_CUR) | 在当前位置不动 |
fseek(file,0L,SEEK_END) | 到文件结尾 |
fseek(file,ftell-pos,SEEK_SET) | 到距文件开始处ftell-pos字节的位置,ftel-pos是ftell的返回值 |
有一点,fseek()和ftell()两个函数是相对于long类型而言,对于更大的数值,ANIS C引入了两个用来处理较大文件的新的定位函数,类型为fpos_t(file position type,文件定位类型)
1.fgetpos()函数原型:int fgetpos(FILE *restrict stream,fpos_t *restrict pos),调用成功返回0,否则非零
2.fsetpos()函数原型:int fsetpos(FILE *stream,const fpos_t *pos),调用成功返回0,否则非零,此处fpos_t的值是通过调用fgetpos()获取的。