std::ofstream 无法在 win7/64 和 msvc2013 上使用 std::ios::ate 打开大文件
Posted
技术标签:
【中文标题】std::ofstream 无法在 win7/64 和 msvc2013 上使用 std::ios::ate 打开大文件【英文标题】:std::ofstream fails to open large files with std::ios::ate on win7/64 and msvc2013 【发布时间】:2015-10-26 03:26:25 【问题描述】:在 windows7 x64 上,我正在尝试修改现有的二进制文件,该文件位于 C: 的根目录中,这是一个 NTFS 文件系统。
以下代码使用 MSVC Community 2013(12.0.31101.00 更新 4)编译:
#include <QFileInfo>
#include <fstream> //std::ifstream
#include <iostream> // std::cout
#include <windows.h>
int main(int argc, char *argv[])
qDebug() << "sizeof(std::size_t):" << sizeof(std::size_t);
const QDir dir("c:\\");
const QStringList fileNames = dir.entryList(QStringList( "*.tst" ), QDir::Files, QDir::Size | QDir::Reversed);
std::ios::openmode m = std::ios::out | std::ios::in | std::ios::binary | std::ios::ate;
for (int i = 0; i < fileNames.size(); i++)
const QString filename = dir.absoluteFilePath(fileNames.at(i));
const QFileInfo fileinfo(filename);
std::ofstream ofs(filename.toLatin1().constData(), m);
qDebug()
<< "ofstream on" << filename
<< "size" << fileinfo.size()
<< "\n\tis_open:" << ofs.is_open()
<< "\n\tgood:" << ofs.good()
<< "\n\tbad:" << ofs.bad()
<< "\n\teof:" << ofs.eof()
<< "\n\tfail:" << ofs.fail()
<< "\n\terror:" << strerror(errno)
<< "\n\tlastError:" << QString::fromStdString(GetLastErrorAsString());
// and now again, but without std::ios::ate
m = std::ios::out | std::ios::in | std::ios::binary;
for (int i = 0; i < fileNames.size(); i++)
const QString filename = dir.absoluteFilePath(fileNames.at(i));
const QFileInfo fileinfo(filename);
std::ofstream ofs(filename.toLatin1().constData(), m);
qDebug()
<< "ofstream on" << filename
<< "size" << fileinfo.size()
<< "\n\tis_open:" << ofs.is_open()
<< "\n\tgood:" << ofs.good()
<< "\n\tbad:" << ofs.bad()
<< "\n\teof:" << ofs.eof()
<< "\n\tfail:" << ofs.fail()
<< "\n\terror:" << strerror(errno)
<< "\n\tlastError:" << QString::fromStdString(GetLastErrorAsString());
输出是:
sizeof(std::size_t): 8
ofstream on "c:/4294967294.tst" size 4294967294
is_open: true
good: true
bad: false
eof: false
fail: false
error: No error
lastError: ""
ofstream on "c:/4294967295.tst" size 4294967295
is_open: false
good: false
bad: false
eof: false
fail: true
error: No error
lastError: ""
ofstream on "c:/4294967294.tst" size 4294967294
is_open: true
good: true
bad: false
eof: false
fail: false
error: No error
lastError: ""
ofstream on "c:/4294967295.tst" size 4294967295
is_open: true
good: true
bad: false
eof: false
fail: false
error: No error
lastError: ""
在 msvc 中编译时,我得到 2>------构建开始:项目:StreamTest,配置:Debug x64 ------ depends.exe 还显示了它的 64 位,并链接到许多 64 位库。
所以我似乎无法使用 std::ios::ate 标志打开文件 >= (2^32)-1 字节。我不敢相信这会发生在具有 NTFS 文件系统的 64 位 Windows 上。我尝试以管理员身份运行此代码...没有区别。
为什么会这样? 我能做什么? (不,我不想使用 boost) msvc 2015 仍然会出现这种情况吗?谢谢!
【问题讨论】:
健全性检查:您的编译平台是 x64 而不是 Win32,对吧? std::size_t 的大小是多少? 脱离 @DanielJour 所说的那样,当您将程序编译为 32 位应用程序时,std::size_t
很可能是一个 32 位无符号整数。如果您正在为 32 位平台编译,由于该值用作文件流的大小存储,因此它将无法存储超过 2^32 - 1 的文件长度。这就是我询问您的编译的原因平台——如果是 Win32,那可能是你的问题。如果是 x64,则有其他问题会导致问题。
首先确保您正在构建一个 64 位程序。如果还是不行,请使用winapi函数进行文件处理。
这是由 VC++ 代码中的错误引起的。构造函数调用_Xfiopen,它调用旧的普通“C”函数fseek。此功能不支持大于 32 位的文件。 fstream:::seekg 正确使用 _fseeki64。
【参考方案1】:
我刚刚下载并安装了 msvc2015 社区版。这个版本没有出现这个问题。
由于其他原因而留在 msvc2013 上,而不是与 std::ios::ate 进行 ORing,我只是
ofs.open("filename", std::ios::out | std::ios::in | std::ios::binary);
ofs.seekp(0, std::ios_base::end);
从std::ios::ate的描述来看,这似乎是等价的,而且目前看来确实有效。
【讨论】:
以上是关于std::ofstream 无法在 win7/64 和 msvc2013 上使用 std::ios::ate 打开大文件的主要内容,如果未能解决你的问题,请参考以下文章
通过 SWIG 在 python 中使用 std::ifstream、std::ofstream 的技术?