【问题标题】:How can we split one 100 GB file into hundred 1 GB file?我们如何将一个 100 GB 的文件拆分为一百个 1 GB 的文件?
【发布时间】:2013-04-03 03:19:33
【问题描述】:

当我试图解决this 问题时,我想到了这个问题。

我有容量为 120 GB 的硬盘,其中 100 GB 被单个大文件占用。所以 20 GB 仍然是免费的。

我的问题是,我们如何将这个巨大的文件分割成更小的文件,比如每个 1 GB?我看到如果我有大约 100 GB 的可用空间,可能使用简单的算法是可能的。但是只给 20 GB 的可用空间,我们最多可以写入 20 个 1GB 的文件。我不知道如何在读取大文件时删除它的内容。

有什么解决办法吗?

一旦我写完一个文件,似乎我必须将文件截断 1 GB,但这归结为这个问题:

是否可以截断文件的一部分?具体如何?

我想看看在 C 或 C++(最好是标准 C 和 C++)中工作的算法(或算法大纲),所以我可能知道较低级别的细节。我不是在寻找可以完成这项工作的神奇函数、脚本或命令。

【问题讨论】:

  • 您必须从源文件的 END 开始工作。分割一个 1gig 的块,将源文件截断 1gig,等等......你不能从前面做,因为这需要你复制整个文件,你会用完空间。
  • @nawaz:抱歉,但我认为拥有 110k 代表的人可以自己通过谷歌搜索 ftruncate() 信息...
  • 只坚持标准功能时必须小心。通常情况下,我不得不求助于非标准扩展来正确处理大于 4GB 的文件。
  • @brianbeuning:可以增加更大文件的大小,然后问同样的问题。所以你的 50 美元无济于事。
  • @Nawaz:如果它正在截断它,那么您打开它时使用了错误的标志。

标签: c++ c algorithm file hard-drive


【解决方案1】:

这项工作没有标准功能。

对于 Linux,您可以使用 ftruncate 方法,而对于 Windows,您可以使用 _chsizeSetEndOfFile。一个简单的#ifdef 将使其跨平台。 另请阅读this问答。

【讨论】:

  • 我编辑了我的问题。现在它说 “我希望看到一个在标准 C 或 C++ 中工作的算法(或算法大纲),所以我可能知道较低级别的细节。我不知道只需要一些可以完成这项工作的解决方案、脚本或命令。”
  • @Nawaz:没有标准的 C++ 工具可以让您跨平台可靠地执行此操作。您需要依赖特定于操作系统的函数,如 _chsizeftruncate,或依赖第三方库,如 boost::filesystem,它们包装了这些函数调用。至少在filesystem 被采纳为标准之前,应该很快。
  • @Nawaz:你所说的低级细节是什么意思?您想让我解释一下如何打开硬盘驱动程序的句柄并使用 FAT32 库自己跟踪文件集群链,以便您自己截断链?如果是这样的话,那么你离跨平台和标准就更远了。
  • @WouterHuysentruit:我的意思是如果我自己实现ftruncate 功能,我会做什么?算法是什么?
  • 只需按照文件集群链修改应该发生截断的集群长度并更新分配表。非常简单,但依赖于文件系统。
【解决方案2】:

根据this question (Partially truncating a stream),您应该能够在符合 POSIX 标准的系统上调用int ftruncate(int fildes, off_t length) 来调整现有文件的大小。

现代实现可能会“就地”调整文件的大小(尽管在文档中未指定)。唯一的问题是您可能需要做一些额外的工作来确保 off_t 是 64 位类型(POSIX 标准中存在 32 位 off_t 类型的规定)。

您应该采取措施处理错误情况,以防万一它由于某种原因失败,因为显然,任何严重的失败都可能导致您的 100GB 文件丢失。

伪代码(假设并采取措施确保所有数据类型都足够大以避免溢出):

open (string filename) // opens a file, returns a file descriptor
file_size (descriptor file) // returns the absolute size of the specified file
seek (descriptor file, position p) // moves the caret to specified absolute point
copy_to_new_file (descriptor file, string newname)
// creates file specified by newname, copies data from specified file descriptor
// into newfile until EOF is reached

set descriptor = open ("MyHugeFile")
set gigabyte = 2^30 // 1024 * 1024 * 1024 bytes

set filesize = file_size(descriptor)
set blocks = (filesize + gigabyte - 1) / gigabyte

loop (i = blocks; i > 0; --i)
    set truncpos = gigabyte * (i - 1)
    seek (descriptor, truncpos)
    copy_to_new_file (descriptor, "MyHugeFile" + i))
    ftruncate (descriptor, truncpos)

显然,其中一些伪代码类似于标准库中的函数。在其他情况下,您必须自己编写。

【讨论】:

  • 除了您的回答,如果还不是很明显,我建议开发人员在实际交易之前在另一个系统上进行测试运行,以确保他们的代码中没有愚蠢的错误......当你只有一次机会时,你想确保你不会错过。 =)
猜你喜欢
  • 2023-03-15
  • 2021-06-11
  • 2014-10-03
  • 1970-01-01
  • 2017-10-02
  • 1970-01-01
  • 2019-03-14
  • 1970-01-01
  • 2018-11-26
相关资源
最近更新 更多