C语言获取文件大小的两种方式

 更新时间:2023年11月06日 09:13:54   作者:mrs_1023  
因为音视频开发的需要,经常会写一些文件输入输出的测试程序,常常用到获取文件大小的函数,本篇文章就记录一下常用的两种获取文件大小的方式,希望对大家有所帮助

因为音视频开发的需要,经常会写一些文件输入输出的测试程序,常常用到获取文件大小的函数。本篇文章就记录一下我常用的两种获取文件大小的方式。

通过文件指针获取文件大小

文件指针 就是调用 fopen() 函数返回的指向FILE结构体的指针,通过文件指针可以对文件进行打开、关闭、读写以及控制读写位置等操作。fopen() 就不做介绍了,这里主要说明用到的另外两个函数。

首先是 fseek(),用来移动文件指针,fseek的用法:

int fseek(FILE *stream, long offset, int whence);
/*
    函数作用:以whence为基点,设置stream的文件指针到偏移offset的位置
    参数说明:
        stream        文件指针
        offset        相对于whence的偏移值
        whence        基准位置,可设置为
                        SEEK_SET (0)    文件头
                        SEEK_CUR (1)    当前位置
                        SEEK_END (2)    文件尾
    返回值:设置成功返回0;设置失败返回-1,并设置errno的值。
 */

另一个就是ftell(),这个函数可以获取文件指针当前位置相对于文件头的偏移,当文件指针指向文件末尾时,ftell() 返回的就是文件的大小。ftell() 函数的用法:

long ftell(FILE *stream);
/*
    函数作用:获取文件指针相对于文件头的偏移值。
    参数说明:
        stream        文件指针
    返回值:获取成功返回当前偏移值;获取失败返回-1,并设置errno的值。
*/

通过文件指针获取文件大小的思路,就是使用fseek将文件指针移动到文件末尾,然后使用ftell获取文件指针相对于文件头的偏移即可得到文件的大小。有一点需要注意,为了不影响对文件的后续操作,需要记录文件指针的初始位置,并在函数退出前将文件指针恢复到初始位置。封装为函数如下:

long get_file_size(FILE *stream)
{
    long file_size = -1;
    long cur_offset = ftell(stream);    // 获取当前偏移位置
    if (cur_offset == -1) {
        printf("ftell failed :%s\n", strerror(errno));
        return -1;
    }
    if (fseek(stream, 0, SEEK_END) != 0) {    // 移动文件指针到文件末尾
        printf("fseek failed: %s\n", strerror(errno));
        return -1;
    }
    file_size = ftell(stream);    // 获取此时偏移值,即文件大小
    if (file_size == -1) {
        printf("ftell failed :%s\n", strerror(errno));
    }
    if (fseek(stream, cur_offset, SEEK_SET) != 0) {    // 将文件指针恢复初始位置
        printf("fseek failed: %s\n", strerror(errno));
        return -1;
    }
    return file_size;
}

通过文件描述符获取文件大小

文件描述符即打开(open)或创建(creat)文件时内核向进程返回的非负整数,内核通过文件描述符访问文件。通过文件描述符获取文件大小只需要一个函数 fstat, fstat可以获取文件的状态,其中就包含文件大小的字段。

对于一个现有文件,一般使用 open() 获取其文件描述符。

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
/*
    函数作用:打开一个文件。
    参数说明:
        pathname        文件路径及文件名
        flag            打开标志,具体参考 open 函数的man-page
        mode            打开模式,具体参考 open 函数的man-page
    返回值:打开成功返回文件描述符;打开失败返回-1,并设置errno的值。
*/

接下来说明 stat 结构体和 fstat() 函数的用法:

struct stat { 
    dev_t st_dev;       // 文件所在设备ID 
    ino_t st_ino;       // 结点(inode)编号  
    mode_t st_mode;     // 保护模式 
    nlink_t st_nlink;   // 硬链接个数  
    uid_t st_uid;       // 所有者用户ID  
    gid_t st_gid;       // 所有者组ID  
    dev_t st_rdev;      // 设备ID(如果是特殊文件) 
    off_t st_size;      // 总体尺寸,以字节为单位 
    blksize_t st_blksize;   // 文件系统 I/O 块大小
    blkcnt_t st_blocks;     // 已分配 512B 块个数
    time_t st_atime;        // 上次访问时间 
    time_t st_mtime;        // 上次更新时间 
    time_t st_ctime;        // 上次状态更改时间 
};
int fstat(int fd, struct stat *statbuf);
/*
    函数作用:获取文件状态。
    参数说明:
        fd            文件描述符
        statbuf        指向文件状态结构体指针
    返回值:获取成功返回0;获取失败返回-1,并设置errno的值。
*/

第一段代码中将文件指针作为了函数的参数,用于文件已使用 fopen() 打开的情况。下面的代码将文件名做为参数,用于文件未被打开的场景。

// 需要的头文件
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

off_t get_file_size(char *file_name)
{
	int ret;
	int fd = -1;
	struct stat file_stat;

	fd = open(file_name, O_RDONLY);	// 打开文件
	if (fd == -1) {
		printf("Open file %s failed : %s\n", file_name, strerror(errno));
		return -1;
	}
	ret = fstat(fd, &file_stat);	// 获取文件状态
	if (ret == -1) {
		printf("Get file %s stat failed:%s\n", file_name, strerror(errno));
		close(fd);
		return -1;
	}
	close(fd);
	return file_stat.st_size;
}

本文主要描述了通过文件指针和文件描述符获取文件大小的两种方式,并且提供了两个参考函数,可以在日常工作中根据需求使用。

到此这篇关于C语言获取文件大小的两种方式的文章就介绍到这了,更多相关C语言获取文件大小内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MoveWindow() SetWindowPos()的区别于联系

    MoveWindow() SetWindowPos()的区别于联系

    这篇文章主要介绍了VC++中MoveWindow() SetWindowPos()的区别于联系,需要的朋友可以参考下
    2015-01-01
  • C语言实现简易停车场管理系统

    C语言实现简易停车场管理系统

    这篇文章主要为大家详细介绍了C语言实现简易停车场管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • VS2022设置编码方式为utf-8的三种方式小结

    VS2022设置编码方式为utf-8的三种方式小结

    本文主要介绍了VS2022设置编码方式为utf-8的三种方式小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-09-09
  • c语言中if 语句的作用范围示例代码

    c语言中if 语句的作用范围示例代码

    if语句的作用范围只有紧跟if的第一条表达式,下面的示例将告诉你,感兴趣的朋友可以了解下
    2013-09-09
  • C++结构体与类的区别详情

    C++结构体与类的区别详情

    这篇文章主要介绍了C++结构体与类的区别,C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据类型的数据结构了,它已经获取了太多的功能。下面我们一起进入文章俩姐具体内容,需要的朋友也可以参考一下
    2021-11-11
  • C语言删除输入字符串中的空格示例代码

    C语言删除输入字符串中的空格示例代码

    最近工作中遇到了需求,要删除字符串中的所有空格,就要筛选出空格字符,这篇文章主要给大家介绍了关于利用C语言删除输入字符串中的空格的相关资料,需要的朋友可以参考下
    2022-12-12
  • C语言结构体超详细讲解

    C语言结构体超详细讲解

    C语言结构体(Struct)从本质上讲是一种自定义的数据类型,只不过这种数据类型比较复杂,是由 int、char、float 等基本类型组成的。你可以认为结构体是一种聚合类型
    2022-04-04
  • 浅谈C语言=与==的区别详解

    浅谈C语言=与==的区别详解

    这篇文章主要介绍了浅谈C语言=与==的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • C语言顺序查找算法介绍及示例

    C语言顺序查找算法介绍及示例

    顺序查找又称线性查找,主要用于在线性表中进行查找。顺序查找通常分为对一般的无序线性表的顺序查找和对按关键字有序的顺序表的顺序查找,下面我们来一探究竟
    2022-08-08
  • 二叉树中叶子节点的统计和树高问题

    二叉树中叶子节点的统计和树高问题

    今天小编就为大家分享一篇关于二叉树中叶子节点的统计和树高问题,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03

最新评论