【问题标题】:How to write data in >4GB file with C++?如何使用 C++ 在 >4GB 文件中写入数据?
【发布时间】:2011-08-21 00:33:37
【问题描述】:

我正在尝试编写一个大文件,但遇到了问题。

我使用 long long 来寻找写的地方,但不能写超过 4,2Gb 的文件。我忘记了什么?

更多详情: 我打开 4Gb 文件:

ifstream ifs(db_name.c_str(), ios_base::binary);
if (!ifs) 
    throw Bad_archive();
ifs.read(as_bytes(seg_size), sizeof(int));
ifs.read(as_bytes(last_idx), sizeof(int));
ifs.read(as_bytes(free_segs), sizeof(int));
if (free_segs > 0)
{
    long long seek_g = 3 * sizeof(int) + (long long)last_idx * seg_size;
    ifs.seekg(seek_g, ios_base::beg);
    for (int i = 0; i < free_segs; i++)
    {
        int tmp = 0;
        ifs.read(as_bytes(tmp), sizeof(int));
        free_spaces.push_back(tmp);
    }
}
ifs.close();

之后,我读取了 400Mb 文件,我想将其添加到数据库中。并写(这里是短代码):

// write object
ofstream ofs(db_name.c_str(), ios_base::binary | ios_base::in | ios_base::ate);
for (int i = 0; ; i++)
{
    // set stream position
    long long write_position = sizeof(int) * 3;

    ...

    write_position += (long long) seg_size * last_idx;
    ofs.seekp(write_position, ios::beg);

            ...

    // write sizeof object
    if (i == 0)
        ofs.write(as_bytes(object_size), sizeof(object_size)); 
    else
    {
        int null = 0;
        ofs.write(as_bytes(null), sizeof(null));
    }

    // write data
    for (int j = 0; j < (seg_size - sizeof(int) * 2); j++)
    {
        ofs.write(as_bytes(obj_content[j + i * (seg_size - sizeof(int) * 2)]), 
        sizeof(char));

    }
    if (write_new_seg)
        last_idx++;

    ...

    ofs.write(as_bytes(cont_seg), sizeof(cont_seg));
}
ofs.close();

之后,我保存数据库信息:

if (last_idx == 0)
{
    ofstream ofs(db_name.c_str());
    ofs.close();
}
ofstream ofs(db_name.c_str(), ios_base::binary | ios_base::in | 
            ios_base::out | ios_base::ate);
long long seek_p = 0;
ofs.seekp(seek_p, ios_base::beg);
ofs.write(as_bytes(seg_size), sizeof(seg_size));
ofs.write(as_bytes(last_idx), sizeof(last_idx));
ofs.write(as_bytes(free_segs), sizeof(free_segs));
ofs.close();

但是这段代码有效:

ofstream ofs2("huge2");
ofs2.close();
ofstream ofs("huge2", ios_base::in | ios_base::ate);
long long sp = 10000000000;
ofs.seekp(10000000000, ios_base::beg);

ofs.write(as_bytes(sp), sizeof(sp));

ofs.close();

【问题讨论】:

  • 您总是可以在一个循环中进行搜索并前进到您想要的点,但是很难跟踪未对齐的偏移量。
  • 许多 C++ 流的实现都停留在上个世纪。当 4 GB 对每个人都足够时。将 char_traits::pos_type 更新为使用 64 个手指计数并不容易,这会破坏现有代码。谈论 int 的赞成答案很明显。

标签: c++ file


【解决方案1】:
    fseeko64 (Filename, 0, SEEK_END);
    long size = ftello64 (Filename);
    fclose (Filename);

访问大文件,fseek不能用,只能用fseeko64();

【讨论】:

    【解决方案2】:

    在 Win32 上有一个名为 _lseeki64() 的函数,在 *nix 上有一个名为 lseek64() 的函数。但是,iostream 库不会直接包装它们,您必须以某种方式检索文件描述符,并做一些缓冲。

    【讨论】:

    • 其实如果他已经在使用平台特定的代码,他可以在Windows下使用(Write|Read)FileOVERLAPPED结构。它支持 8 字节的偏移量,尽管您可以一次“仅”写入 4gb。我假设在 POSIX 中定义了一些类似的舒适功能。
    【解决方案3】:

    许多filesystems 不支持大于 4GB 的文件。此外,您应该考虑到您的int 类型可能有一个以2^32 结尾的范围,即4.29497e+09。

    【讨论】:

    • 1.我有NTFS。 2.我知道int。我对在这种情况下可能被过度填充的变量使用 long long。
    • 但这并不是真正的解释。 c 标准要求类型至少有 8 字节宽度,以便他们可以使用其中之一添加函数。还有一些文件系统不允许超过 32MB,所以今天已经存在值太大的问题..
    • @Voo:是的,当然这个问题一直存在,除非有一些我不知道的历史文件系统曾经允许无限大小的文件。跨度>
    【解决方案4】:

    这里有一个很好的 Linux 总结:

    http://www.suse.de/~aj/linux_lfs.html

    RedHat 针对 RHEL 的更具体细节,这些问题通常是针对 32 位应用程序访问 64 位大小的文件。

    http://people.redhat.com/berrange/notes/largefile.html

    维基百科实际上在Large File Support 上有一篇文章,但信息量并不大。

    【讨论】:

      猜你喜欢
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-05
      相关资源
      最近更新 更多