# 获取文件大小 实际开发中,有时候需要先获取文件大小再进行下一步操作。C语言没有提供获取文件大小的函数,要想实现该功能,必须自己编写函数。 ## ftell()函数 ftell() 函数用来获取文件内部指针(位置指针)距离文件开头的字节数,它的原型为: ```c long int ftell(FILE *fp); ``` 注意:fp 要以二进制方式打开,如果以文本方式打开,函数的返回值可能没有意义。 先使用 fseek() 将文件内部指针定位到文件末尾,再使用 ftell() 返回内部指针距离文件开头的字节数,这个返回值就等于文件的大小。请看下面的代码: ```c long fsize(FILE *fp){ fseek(fp, 0, SEEK_END); return ftell(fp); } ``` 这段代码并不健壮,它移动了文件内部指针,可能会导致接下来的文件操作错误。例如: ```c long size = fsize(fp); fread(buffer, 1, 1, fp); ``` fread() 函数将永远读取不到内容。所以,获取到文件大小后还需要恢复文件内部指针,请看下面的代码: ```c long fsize(FILE *fp){ long n; fpos_t fpos; //当前位置 fgetpos(fp, &fpos); //获取当前文件内部指针 fseek(fp, 0, SEEK_END); //将文件指针移动到文件末尾 n = ftell(fp); fsetpos(fp, &fpos); //回复文件内部指针位置 return 0; } ``` fpos_t 是在 stdio.h 中定义的结构体,用来保存文件的内部指针。fgetpos() 用来获取文件内部指针,fsetpos() 用来设置文件内部指针。 【文件大小实例】 ```c #include #include long fsize(FILE *fp); int main() { long size = 0; FILE *fp = NULL; char filename[30] = "wang.txt"; if ((fp = fopen(filename, "rb")) == NULL) { printf("%s: No such file exist.\n", filename); exit(EXIT_FAILURE); } printf("%s: %ld Bytes.\n", filename, fsize(fp)); return 0; } long fsize(FILE *fp) { long n; fpos_t fpos; fgetpos(fp, &fpos); //将当前文件内部指针保存到fpos fseek(fp, 0, SEEK_END); //移动文件内部指针到文件末尾 n = ftell(fp); fsetpos(fp, &fpos); //将文件内部指针还原到开始位置 return n; } ``` 这个查询的文件名是写在源码之中的,我们再次升级一下,将要查询的文件名写成控制台参数。 ```c #include #include long fsize(FILE *fp); int main(int argc, char *argv[]) { if (argc < 2) { printf("缺少要查询的文件."); exit(EXIT_FAILURE); } long size = 0; FILE *fp = NULL; char *filename = argv[1]; if ((fp = fopen(filename, "rb")) == NULL) { printf("%s: No such file exist.\n", filename); exit(EXIT_FAILURE); } long nBytes = fsize(fp); double nMBytes = nBytes / (1024 * 1024 * 1.0); printf("%s: %ld Bytes(%lf MB).\n", filename, nBytes, nMBytes); return 0; } long fsize(FILE *fp) { long n; fpos_t fpos; fgetpos(fp, &fpos); //将当前文件内部指针保存到fpos fseek(fp, 0, SEEK_END); //移动文件内部指针到文件末尾 n = ftell(fp); fsetpos(fp, &fpos); //将文件内部指针还原到开始位置 return n; } ```