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 打开大文件的主要内容,如果未能解决你的问题,请参考以下文章

std::ofstream,写入前检查文件是不是存在

std::ofstream::write 添加字符

通过 SWIG 在 python 中使用 std::ifstream、std::ofstream 的技术?

如何将 std::ofstream& 传递给功能参数?

为啥我可以在临时 std::ofstream 对象上使用 `operator<<`?

C++学习(四七零)std::ofstream