c++ - 可以打开小的 ASCII 文件,但不能打开大的二进制文件吗?

标签 c++ c file c++11 large-files

我正在使用以下代码在 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 版本上运行。否则,内存address space is limited在 32 位 Windows 和 4 GB with 32 bits code on a 64 bits Windows 上最大 3 GB .

顺便说一下,ftell()返回一个带符号的 long。您必须检查这里没有错误(例如,如果操作系统允许更大的文件大小则发生溢出),因此该值不是 -1。

编辑:

请注意 with MSVC, long will currently be即使编译为 64 位,也是 32 位数字。这意味着如果文件大小低于 2GB(因为符号),ftell() 将为您提供有意义的结果。

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

malloc() 接受一个 size_t,它是一个 unsigned 64 bit number .所以在这一边你是安全的。

另一种方法是使用 file mapping .

第二次编辑

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

查看this CERT security recommendation ,似乎 fseek() 标准与 SEEK_END 结合提供的保证是不充分的,这使它成为一种非常不安全的方法。

让我们重申一下:获取大小的最安全方法是使用 native 操作系统函数,即 Windows 上的 GetFileSizeEx()。在 64 位 Windows 上有一个解决方法:使用 _fseeki64()_ftelli64():

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

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

关于c++ - 可以打开小的 ASCII 文件,但不能打开大的二进制文件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39677947/

相关文章:

c++ - 如何替换具有 double 类型的模板参数?

c++ - 如何在 DirectX11 中围绕其局部轴之一旋转对象

c - 找到节点后从链表中删除节点

c - malloc 复制中的段错误

c++ - 了解 C 中的基数排序

c++ - 如何将模板名称传递给方法?

c - 如何在内存中表示极大的 float ?

c#保持文件打开但覆盖内容

c - 如何比较链表中的条目?

c - c 中的 null 类型和编译器错误