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

Posted 人生海海 山山而川

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++通过文件指针获取文件大小相关的知识,希望对你有一定的参考价值。

1. 叙述

对于读取本地文件,很多时候需要预先知道本地文件的大小在进行读取。网上给出的方案是移动文件指针,计算文件头和文件尾的偏移,计算出文件的大小。但是我总觉得这样做可能会与读取文件一样消耗性能,为了解决这个问题,我写了如下例子验证了一下。

#include <iostream>
#include <fstream>
#include<Windows.h>

using namespace std;

class CTimer
{
public:
	CTimer(void);
	~CTimer(void);

	int time_in();
	double time_out();

private:
	LARGE_INTEGER litmp;
	LONGLONG qt1, qt2;
	double dft, dff, dfm;
};

CTimer::CTimer(void)
{
}


CTimer::~CTimer(void)
{
}

int CTimer::time_in()
{
	QueryPerformanceFrequency(&litmp);//获得时钟频率
	dff = (double)litmp.QuadPart;

	QueryPerformanceCounter(&litmp);//获得初始值
	qt1 = litmp.QuadPart;

	return 1;
}

double CTimer::time_out()
{
	QueryPerformanceCounter(&litmp);//获得终止值
	qt2 = litmp.QuadPart;

	dfm = (double)(qt2 - qt1);
	dft = dfm / dff;//获得对应的时间值

	return dft;
}


int main()
{
	string file_name = "D:/Work/test.zip";
	CTimer timer;

	ifstream ifs(file_name, std::ios::binary | std::ios::in);
	if (!ifs.is_open())
	{
		return 0;
	}

	
	timer.time_in();
	ifs.seekg(0, std::ios::end);
	int len = ifs.tellg();
	ifs.seekg(0, std::ios::beg);
	cout << "获取文件长度耗时:" << timer.time_out() << "秒" << endl;

	timer.time_in();

	char *buff = new char[len];

	ifs.read(buff, len);
	delete[]buff;

	timer.time_out();
	cout << "读取文件耗时:" << timer.time_out() << "秒" << endl;

	return 1;
}

如上所示,我写了一个计时器,分别统计偏移文件指针计算文件长度与读取整个文件的耗时,运行结果如下:

2. 结论

可以看到,偏移文件指针带来的时间消耗非常小,几乎可以忽略不记。通过这个方法,不仅可以很快计算文件长度,还可以根据需要读取文件的特定位置,从而达到节省性能的目的。

C 语言文件操作 ( ftell 函数 | 使用 ftell 函数获取当前指针位置 | 通过 ftell 计算文件大小 )





一、ftell 函数



ftell() 函数的作用是 获取文件的 当前指针位置 相对于 文件首地址偏移字节数 ;


ftell 函数原型 :

#include <stdio.h>
long ftell(FILE *stream);

ftell 使用场景 : 随机方式存取文件时 , 使用 fseek 函数来回移动指针 , 不容易确定当前指针位置 , 通过调用 ftell 函数确定指针位置 ;





二、使用 ftell 函数获取当前指针位置



代码示例 :

  • 第一次打印指针位置 : 刚打开文件 , 还未读取数据 , 指针指向 0 位置 , 索引 0 ;
  • 第二次打印指针位置 : 跳过了 4 字节数据 , 偏移了 4 字节 , 指针指向第 5 字节 , 索引 4 ;
  • 第三次打印指针位置 : 跳过了 4 字节数据 , 又向后读取 2 字节 , 偏移了 6 字节 , 指向第七字节 , 索引 6 ;
#include <stdio.h>

int main()

    // 以写文本的方式向文件中写出数据
    FILE *p = fopen("D:/File/number.dat", "w");
    // 写出 10 个字符
    char array[10] = 1,2,3,4,5,6,7,8,9,10;
    // 将 10 个字符写出到文件中
    fwrite(array, 1, sizeof(array), p);
    // 关闭文件
    fclose(p);




    // 跳过 4 字节读取文件 2 字节
    FILE *p2 = fopen("D:/File/number.dat", "r");

    // 使用 ftell 函数获取当前指针位置
    int location = ftell(p2);
    // 刚打开文件 , 还未读取数据 , 指针指向 0 位置 ★★★
    printf("location = %d\\n", location);

    // 读取数据缓冲区
    char array2[2];

    // 跳过 4 字节 , 此时当前位置是 0
    fseek(p2, 4, SEEK_CUR);

    // 使用 ftell 函数获取当前指针位置
    location = ftell(p2);
    // 跳过了 4 字节数据 , 偏移了 4 字节 ,
    // 指针指向第 5 字节 , 索引 4 ★★★
    printf("location = %d\\n", location);

    // 读取 2 字节
    fread(array2, 1, sizeof(array2), p2);
    // 打印前 2 字节数据
    printf("%d , %d\\n", array2[0], array2[1]);

    // 使用 ftell 函数获取当前指针位置
    location = ftell(p2);
    // 跳过了 4 字节数据 , 又向后读取 2 字节 ,
    // 偏移了 6 字节 , 指向第七字节 , 索引 6 ★★★
    printf("location = %d\\n", location);

    return 0;


执行结果 :





三、通过 ftell 计算文件大小



代码示例 : 打开文件后 , 直接使用 fseek 跳转到文件末尾 , 然后使用 ftell 获取当前指针 , 打印出指针位置 , 即可获取文件大小 ;

#include <stdio.h>

int main()

    // 以写文本的方式向文件中写出数据
    FILE *p = fopen("D:/File/number.dat", "w");
    // 写出 10 个字符
    char array[10] = 1,2,3,4,5,6,7,8,9,10;
    // 将 10 个字符写出到文件中
    fwrite(array, 1, sizeof(array), p);
    // 关闭文件
    fclose(p);




    // 先打开文件
    FILE *p2 = fopen("D:/File/number.dat", "r");

    // 将文件指针移动到文件末尾
    fseek(p2, 0, SEEK_END);

    // 使用 ftell 函数获取当前指针位置
    int location = ftell(p2);

    // 通过读取当前文件指针位置, 即可获取文件大小 ★★★
    printf("filesize = %d\\n", location);

    // 将文件指针恢复
    fseek(p2, 0, SEEK_SET);

    // 使用 ftell 函数获取当前指针位置
    location = ftell(p2);

    // 查看指针是否恢复 ★★★
    printf("location = %d\\n", location);

    return 0;


执行结果 :

以上是关于C++通过文件指针获取文件大小的主要内容,如果未能解决你的问题,请参考以下文章

C++中怎样获取一个文件的大小,怎样判断一个文件是不是为空(文件存在,但是没有内容)

更新:C++ 指针片段

GCC - 在没有链接描述文件的情况下获取自定义部分的大小

C++移动和获取文件读写指针(seekpseekgtellgtellp)

MFC编程 -- 读取文件内容

在 C++ 中,如何获取指向向量的指针?