【问题标题】:std::ofstream fails to open large files with std::ios::ate on win7/64 and msvc2013std::ofstream 无法在 win7/64 和 msvc2013 上使用 std::ios::ate 打开大文件
【发布时间】: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。

标签: c++ c++11 stream std


【解决方案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的描述来看,这似乎是等价的,而且目前看来确实有效。

【讨论】:

    猜你喜欢
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 2010-10-23
    • 1970-01-01
    • 2020-11-03
    • 2017-08-10
    • 1970-01-01
    相关资源
    最近更新 更多