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语言获取文件大小内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言创建动态dll和调用dll(visual studio 2013环境下)

    C语言创建动态dll和调用dll(visual studio 2013环境下)

    本篇文章主要介绍了C语言创建动态dll和调用dll(visual studio 2013环境下),非常具有实用价值,需要的朋友可以参考下
    2017-11-11
  • 详解_beginthreadex()创建线程

    详解_beginthreadex()创建线程

    这篇文章主要介绍了详解_beginthreadex()创建线程,使用_beginthreadex(),需要的头文件支持#include <process.h> 下面我们就来看看具体的实现吧
    2022-01-01
  • C++宏函数和内联函数的使用

    C++宏函数和内联函数的使用

    本文主要介绍了C++宏函数和内联函数的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • C语言实现页面置换 先进先出算法(FIFO)

    C语言实现页面置换 先进先出算法(FIFO)

    这篇文章主要为大家详细介绍了C语言实现页面置换,先进先出算法(FIFO),文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • C++设计模式编程中Template Method模板方法模式的运用

    C++设计模式编程中Template Method模板方法模式的运用

    这篇文章主要介绍了C++设计模式编程中Template Method模板方法模式的运用,讲到了包括模板方法模式中的细分方法以及适用场景,需要的朋友可以参考下
    2016-03-03
  • C++人工模拟栈实现方法

    C++人工模拟栈实现方法

    在本篇内容里小编为大家整理了关于C++人工模拟栈实现方法和步骤,需要的朋友们可以学习下。
    2018-12-12
  • C++ 继承的范例讲解

    C++ 继承的范例讲解

    继承是C++面向对象编程中的一门。继承是子类继承父类的特征和行为,或者是继承父类得方法,使的子类具有父类得的特性和行为。重写是子类对父类的允许访问的方法实行的过程进行重新编写,返回值和形参都不能改变。就是对原本的父类进行重新编写,但是外部接口不能被重写
    2022-06-06
  • C语言实现数字雨效果

    C语言实现数字雨效果

    这篇文章主要为大家详细介绍了C语言实现数字雨效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • 详解C语言中动态内存管理

    详解C语言中动态内存管理

    这篇文章主要为大家详细介绍了C语言中动态内存管理的相关知识,以及常见的动态内存的错误,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-07-07
  • c++中的两种getline用法详解

    c++中的两种getline用法详解

    c++中有2种getline函数,一种在头文件 <istream> 中,是istream类的成员函数;另一种是在头文件 <string> 中,是普通函数。这篇文章主要介绍了c++中的两种getline用法,需要的朋友可以参考下
    2020-02-02

最新评论