可以打开小型ASCII文件,但不能打开大型二进制文件
Can open small ASCII file, but not large binary file?
我使用以下代码在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(读取文件大小。
- 是否可以将函数导入命名空间,但不能导出它?
- std::unique_ptr 在 GCC 中工作,但不能在 Visual Studio 中编译
- 声明C++具有动态大小的数组类型在 Linux 中工作正常,但不能在 Windows 中工作
- 为什么我可以隐式地将字符*转换为常量字符*,但不能将无符号字符*
- std::chrono::d uration 可以按秒初始化,但不能按毫秒初始化?
- Python/C++:可以导入犰狳(arma::)但不能导入子程序arma::arma_rng::randn
- 为什么我可以从C++文件中读取 int 值,但不能浮点?
- C++程序在将 int 与 cin 一起使用时有效,但不能使用字符串
- SqLite c++,可以创建数据库,但不能将 anthing 插入到表中
- std::remove() 按预期处理文字,但不能与取消引用的迭代器一起工作
- 16 位系统中的程序如何访问大于 65535 的整数,但不能访问地址
- C++:返回本地对象,但不能正常工作
- 可以访问一个类中的播放器结构,但不能访问另一个类中的播放器结构
- 返回实例变量的c++方法可以访问变量中的数据,但不能更改它,但在编译时不会生成错误
- 用C++替换std::字符串中的一个子字符串,但不能全部替换
- 我可以在Windows(Visual C++)中读取bin文件,但不能在linux(GCC)上读取bin文件
- QProcess可以启动程序,但不能启动python(命令行)
- C++11 向量包含 2 个不同的子类,但不能同时进行
- Eclipse 中的 Makefile 项目可以运行,但不能调试,为什么?
- 可以打开小型ASCII文件,但不能打开大型二进制文件