Windows 10 x64下fopen打开13GB大文件ftell返回0的问题咨询
我之前在处理大文件的时候也碰到过一模一样的问题,给你拆解下原因和解决办法~
问题根源
你遇到的问题本质是传统C标准库的ftell/fseek函数默认使用32位整数存储文件偏移量,在32位程序中,这个偏移量的最大值是2^31-1字节(约2GB)。当文件大小超过这个值时,32位整数会溢出,导致ftell返回错误值(比如你看到的0),同时errno会被设置为EOVERFLOW(你可以在调用后检查这个值确认)。
虽然你用的是Windows 10 x64系统,但如果你的程序是32位编译的,依然会受这个限制;哪怕是64位编译,默认的标准库函数也可能需要额外配置才能支持大文件。
解决方案
这里有几种靠谱的解决方式,你可以根据自己的需求选:
1. 64位编译+宏定义兼容传统函数
如果想继续用fopen/fseek/ftell这套熟悉的接口,只需两步:
- 把你的项目编译目标改成x64(而不是x86)
- 在包含头文件之前,定义
_FILE_OFFSET_BITS=64宏,这样传统函数会自动映射到64位版本
示例代码:
#define _FILE_OFFSET_BITS 64 #include <stdio.h> #include <errno.h> long long get_large_file_size(const char* file_path) { FILE* fp = fopen(file_path, "rb"); if (!fp) { // 处理打开失败的情况 return -1; } // 跳转到文件末尾 if (fseek(fp, 0, SEEK_END) != 0) { fclose(fp); return -1; } // 此时ftell实际是_ftelli64的别名,返回64位大小 long long file_size = ftell(fp); if (file_size == -1 && errno == EOVERFLOW) { // 确认是大文件溢出问题 fclose(fp); return -2; } fclose(fp); return file_size; }
2. 直接使用64位版本的标准库函数
如果你不想改编译目标,或者需要更明确地处理大文件,可以直接调用MSVC提供的64位专属函数_fseeki64和_ftelli64:
示例代码:
#include <stdio.h> long long get_large_file_size(const char* file_path) { FILE* fp = fopen(file_path, "rb"); if (!fp) { return -1; } // 用64位版本的fseek跳转到末尾 if (_fseeki64(fp, 0, SEEK_END) != 0) { fclose(fp); return -1; } // 获取64位文件大小 long long file_size = _ftelli64(fp); fclose(fp); return file_size; }
3. 调用Windows原生API(最可靠)
如果追求最高的兼容性和准确性,直接用Windows的原生文件操作APICreateFile和GetFileSizeEx,完全不受标准库的限制:
示例代码:
#include <windows.h> long long get_large_file_size(const wchar_t* file_path) { // 打开文件,只读模式 HANDLE h_file = CreateFileW( file_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (h_file == INVALID_HANDLE_VALUE) { return -1; } LARGE_INTEGER file_size; // 获取64位文件大小 GetFileSizeEx(h_file, &file_size); CloseHandle(h_file); return file_size.QuadPart; }
额外提示
- 不管用哪种方法,记得在操作文件后及时关闭句柄/文件指针,避免资源泄漏
- 如果是32位程序,即使解决了文件大小获取的问题,后续读写大文件时也要注意内存限制,毕竟32位程序的地址空间只有4GB左右
内容的提问来源于stack exchange,提问作者Edoardo Luciani
相关产品推荐
相关产品推荐

