可以打开小型ASCII文件,但不能打开大型二进制文件

Can open small ASCII file, but not large binary file?

本文关键字:但不能 大型 二进制文件 ASCII 小型 文件      更新时间:2023-10-16

我使用以下代码在Windows上的MSVC中打开一个大的(5.1GB(二进制文件。这台机器内存充足。问题是长度被检索为零。但是,当我将file_path更改为较小的ASCII文件时,代码工作正常。

为什么我不能加载大的二进制文件?我更喜欢这种方法,因为我想要一个指向文件内容的指针。

FILE * pFile;
uint64_t lSize;
char * buffer;
size_t result;
pFile = fopen(file_path, "rb");
if (pFile == NULL) { 
    fputs("File error", stderr); exit(1); 
}
// obtain file size:
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);                                // RETURNS ZERO
rewind(pFile);
// allocate memory to contain the whole file:
buffer = (char*)malloc(sizeof(char)*lSize);
if (buffer == NULL) {
    fputs("Memory error", stderr); exit(2); 
}
// copy the file into the buffer:
result = fread(buffer, 1, lSize, pFile);             // RETURNS ZERO TOO
if (result != lSize) {                               // THIS FAILS
    fputs("Reading error", stderr); exit(3); 
}
/* the whole file is now loaded in the memory buffer. */

这不是文件权限或其他什么问题,它们很好。

如果您分配了5.1 GB,您最好确保您已经用64位编译了代码,并在64位windows版本上运行它。同时,内存地址空间在32位Windows上限制为最大3 GB,在64位Windows上则限制为4 GB(32位代码(。

顺便说一下,ftell()返回一个已签名的long。您必须检查这里是否没有错误(例如,如果操作系统允许更大的文件大小,则会出现溢出(,以便值不是-1。

编辑:

注意,对于MSVC,long当前将是32位数字,即使编译为64位。这意味着如果文件大小低于2GB(因为符号(,ftell()将给你一个有意义的结果。

您可以使用不可移植的特定于操作系统的WinAPI函数GetFileSizeEx()来获取带符号的64位数字中的大文件的大小。

CCD_ 6取一个CCD_。所以在这一边你是安全的。

另一种选择是使用文件映射。

第二次编辑

我查看了您对收到的大小值的编辑,这与我的预期不同。我可以在我的系统上重现错误,并得到一个不为空的大小,但它是一个比文件大得多的数字。

从CERT的安全建议来看,fseek()标准与SEEK_END标准相结合所提供的保证似乎是低效的,这使得这是一种非常不安全的方法。

因此,让我们重复一下:获取大小的最简单方法是使用本机操作系统功能,即Windows上的GetFileSizeEx()。在64位窗口上有一个变通方法:使用_fseeki64()_ftelli64():

...
if (_fseeki64(pFile, 0, SEEK_END)) {
    fputs("File seek error", stderr); 
    return (1);
}
lSize = _ftelli64(pFile);                            // RETURNS EXACT SIZE
...

这非常有效(最初的问题似乎与返回类型不够大有关(。但是请记住,这是一种变通方法,我担心可能会有其他错误情况导致CERT报告的漏洞。

数据类型long太小,无法表示文件大小。使用stat((方法(或Windows特定的替代GetFileAttributes(读取文件大小。

相关文章: