编程开发中,获取文件大小是一项常见的需求,无论是进行文件管理、数据传输还是资源监控等操作,都可能需要知道文件的具体大小。下面将介绍几种常见的获取文件大小的方式,并进行对比分析。
几种可行的文件大小获取方式
1. 使用 fseek
和 ftell
函数
此方法借助标准 C 库函数,先把文件指针移至文件末尾,再获取当前指针位置以得到文件大小。其中fseek
函数用于移动文件指针的位置,ftell
函数用于获取当前文件指针相对于文件开头的偏移量。
#include <stdio.h>
long getFileSizeUsingFseek(const char* filename) {
FILE* file = fopen(filename, "rb");
if (file == NULL) {
perror("fopen");
return -1;
}
if (fseek(file, 0, SEEK_END) != 0) {
perror("fseek");
fclose(file);
return -1;
}
long size = ftell(file);
fclose(file);
return size;
}
2. 使用 _stat
(Windows)/stat
(类 Unix)函数
_stat
是 Windows 平台函数,stat
是类 Unix 平台函数,它们都可以直接从文件系统元数据中获取文件的相关信息,包括文件大小。
#include <stdio.h>
#include <sys/stat.h>
#ifdef _WIN32
long getFileSizeUsingStat(const char* filename) {
struct _stat fileStat;
if (_stat(filename, &fileStat) == 0) {
return fileStat.st_size;
} else {
perror("_stat");
return -1;
}
}
#else
long getFileSizeUsingStat(const char* filename) {
struct stat fileStat;
if (stat(filename, &fileStat) == 0) {
return fileStat.st_size;
} else {
perror("stat");
return -1;
}
}
#endif
3. 使用 _filelength
函数(Windows)
_filelength
是 Windows 平台特有的函数,用于获取文件的大小,它需要先通过 _fileno
函数将文件指针转换为文件描述符(file descriptor)。
#include <stdio.h>
#include <io.h>
__int64 getFileSizeUsingFilelength(const char* filename) {
FILE* file = fopen(filename, "rb");
if (file == NULL) {
perror("fopen");
return -1;
}
__int64 size = _filelengthi64(_fileno(file));
fclose(file);
return size;
}
4. 使用 std::filesystem::file_size
(C++17)
C++17 引入的 std::filesystem
库,提供了 file_size
函数用于获取文件大小。
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
std::uintmax_t getFileSizeUsingFilesystem(const std::string& filename) {
try {
return fs::file_size(filename);
} catch (const fs::filesystem_error& e) {
std::cerr << "Error: " << e.what() << '\n';
return static_cast<std::uintmax_t>(-1);
}
}
几种方式的对比分析
1.性能方面
fseek
+ftell
方法:该方法需要对文件进行操作,将文件指针移动到文件末尾。在操作过程中,可能会涉及到磁盘寻道等操作,尤其是对于大文件,性能开销相对较大。因为大文件可能存储在磁盘的不同位置,移动文件指针到末尾可能会导致更多的磁盘寻道。_stat
/stat
方法:直接从文件系统元数据中获取文件大小,避免了文件指针的移动和相关的磁盘操作。文件系统通常会将文件元数据缓存在内存中,所以这种方法速度较快,且不受文件大小的影响。_filelength
方法:需要先将文件指针转换为文件描述符fd(file descriptor),再获取文件大小,涉及额外的函数调用和转换操作。由于该函数是通过fd,因此有理由相信也是通过文件系统元数据来获取文件大小数据,考虑到是windows系统提供的库函数,性能应该和_stat
/stat
方法类似甚至更快。std::filesystem::file_size
:底层实现与_stat
/stat
类似,直接访问文件系统元数据,性能较好。其实现依赖操作系统和标准库,多数情况下性能与_stat
/stat
相当。
2.可移植性方面
fseek
+ftell
方法:标准 C 库函数,在 Windows 和类 Unix 平台上都有实现,具有良好的跨平台性。_stat
/stat
方法:在
POSIX标准中有定义,但 Windows和类 Unix 平台的函数命稍有差异(_stat
是 Windows 特定函数,stat
是类 Unix 标准函数),需要通过条件编译来实现跨平台代码。_filelength
方法:Windows 平台特有函数,不具备跨平台性。std::filesystem::file_size
方法:作为C++17 标准库的一部分,跨平台性好,只要编译器支持 C++17 及以上标准,在不同操作系统都能使用。
结论
- 若追求跨平台且代码简洁,C++17 的
std::filesystem::file_size
是首选,它提供了统一接口,错误处理更完善; - 如果追求高性能,尤其是需要处理大量文件的大小获取,
_stat
/stat
方法更为合适。Windows 系统可使用_filelengthi64;
- 若在老项目中,C++17 标准不可用且对性能要求不是极高,
fseek
+ftell
作为经典方法还是一个可用的选择。