有三种方法可以使用 C 语言取得文件大小,前两种实际上是取得文件的总字符数,也许仅对普通文件和二进制文件有效。
- ftell 和 fseek 调用
- lseek 系统调用
- fstat 调用以及 stat 成员 st_size
stdio.h
/*
* fseek 通过移动文件指针所指向的字符来达到随机读取文件的目的,还可以和 ftell 函数搭配取得文件的字符数。
* 手册页是这样介绍 fseek 的
* The fseek() function sets the file position indicator for the stream pointed to by stream. The new position, measured in bytes, is obtained by adding offset bytes to the position specified by whence.
* If whence is set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to the start of the file, the current position indicator, or end-of-file, respectively.
* A successful call to the fseek() function clears the end-of-file indicator for the stream and undoes any effects of the ungetc(3) function on the same stream.
* offset 是一个偏移量,代表了文件指针每次移动时希望移动的字符数,只有文件开始和文件结束的地方才可以是 0 和负数。
* whence 用来设置移动到的最终位置,是一个宏,在 unistd.h 中定义。
* SEEK_SET = 0,SEEK_CUR = 1,SEEK_END = 2 相对于文件的开始,当前位置指示符或文件结尾。
*/
int fseek(FILE *stream, long offset, int whence);
/*
* ftell 函数会返回文件指针所指向的字符的位置,参数 strem 是一个有效的 fopen 调用返回的有效 FILE 指针
*/
long ftell(FILE *stream);
unistd.h
/*
* lseek 系统调用成功后将返回从文件开始以字节计的结果偏移量(即文件的总字符数,如果打开文件后没有做其它事情而仅仅将指针移动到文件的结尾字符的话)。
* 否则,-1 返回,errno 被设置为一个错误码,文件偏移量保持不变。
* fildes 是一个 open 系统调用成功后返回的有效文件描述符,为一非负整数
*/
off_t lseek(int fildes, off_t offset, int whence);
/*
* stat 结构定义了与文件属性相关的成员,但访问这些成员之前需要先使用调用 fstat() 获取文件信息保存到 stat 结构中.....
*/
sys/stat.h
struct stat;
int fstat(int fildes, struct stat *buf);
fsz.c
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/stat.h>
/* 系统调用 lseek */
off_t fsize_lseek(const char *file)
{
int fd;
if(-1 == (fd = open(file,O_RDONLY))){
perror("open file error");
exit(EACCES);
}
off_t len = lseek(fd,0,SEEK_END);
close(fd);
printf("**** %s call: ****\n",__FUNCTION__);
return len;
}
/* ftell 调用 */
unsigned long fsize_ftell(const char *file)
{
FILE *fp;
if(!(fp = (fopen(file,"r")))){
perror("open fiile error");
exit(EACCES);
}
unsigned long end_c;
//fseek(fp,0,SEEK_SET);
//start_ = ftell(fp);
if(-1 == fseek(fp,0,SEEK_END)){
perror("fseek call error");
}
end_c = (unsigned)ftell(fp);
fclose(fp);
fp = NULL;
printf("**** %s call: ****\n",__FUNCTION__);
return end_c;
}
/* fstat 调用 */
off_t fsize_fstat(const char *file)
{
struct stat st;
int fd;
if(-1 == (fd = open(file,O_RDONLY))){
perror("open file error");
exit(EACCES);
}
fstat(fd,&st);
close(fd);
printf("**** %s call: ****\n",__FUNCTION__);
return st.st_size;
}
int main(int argc,char **argv)
{
if(argc != 2){
fprintf(stderr,"Usage:%s <file>\n",argv[0]);
return EINVAL;
}
printf("%s %ld bytes.\n",argv[1],fsize_ftell(argv[1]));
printf("%s %ld bytes.\n",argv[1],fsize_fstat(argv[1]));
printf("%s %ld bytes.\n",argv[1],fsize_lseek(argv[1]));
}
编译,运行结果如下:
make fsz
./fsz `which ls`;ls -l `which ls`
**** fsize_ftell call: ****
/usr/bin/ls 130552 bytes.
**** fsize_fstat call: ****
/usr/bin/ls 130552 bytes.
**** fsize_lseek call: ****
/usr/bin/ls 130552 bytes.
-rwxr-xr-x 1 root root 130552 3月 12 22:09 /usr/bin/ls
./fsz /etc/fstab;ls -l /etc/fstab
**** fsize_ftell call: ****
/etc/fstab 534 bytes.
**** fsize_fstat call: ****
/etc/fstab 534 bytes.
**** fsize_lseek call: ****
/etc/fstab 534 bytes.
-rw-r--r-- 1 root root 534 6月 4 02:18 /etc/fstab