【问题标题】:Truncate file at front在前面截断文件
【发布时间】:2010-10-16 21:51:00
【问题描述】:

我最近正在处理的一个问题让我希望我可以去掉文件的前面。有点像“前面截断”,如果你愿意的话。在后端截断文件是一种常见的操作——我们甚至没有考虑太多。但是去掉文件的前面?一开始听起来很荒谬,但这只是因为我们被训练认为这是不可能的。但 lop 操作在某些情况下可能很有用。

一个简单的例子(当然不是唯一或最好的例子)是 FIFO 队列。您正在将新项目添加到文件的末尾并从文件前面拉出项目。该文件随着时间的推移而增长,前面有一个巨大的空白空间。对于当前的文件系统,有几种方法可以解决这个问题:

  • 删除每个项目后,复制 剩下的项目来替换它,和 截断文件。虽然有效, 这个解决方案非常昂贵 时间方面。
  • 监控空白空间的大小 前面,当它到达一个 特定大小或百分比 整个文件大小,向上移动所有内容 并截断文件。这是很多 比以前更有效率 解决方案,但仍然需要时间 项目在文件中移动。
  • 在 文件,将新项目添加到孔中 文件的前面作为项目是 删除。这可以是相当有效的, 特别是如果你不介意 事情脱离的可能性 队列中的顺序。如果你在乎 关于秩序,有可能 不得不四处移动物品。但在 一般来说,圆形队列很漂亮 易于实施和管理磁盘 空间很好。

但是如果有一个 lop 操作,从队列中删除一个项目就像更新文件开头标记一样简单。事实上,就像截断文件一样简单。那么,为什么没有这样的操作呢?

我对文件系统的实现有一点了解,并且没有看到任何特殊原因这会很困难。在我看来,它所需要的只是每个分配条目的另一个词(dword,也许是?)来说明文件在块内的开始位置。对于 1 TB 的驱动器低于 100 美元,为此类功能付出的代价似乎很小。

如果您可以像在结尾处截断一样有效地删除文件的前面,那么还有哪些任务会变得更容易?

您能想到什么技术原因无法将此功能添加到现代文件系统中吗?其他非技术原因?

【问题讨论】:

  • 这种操作的一大优点是它可以避免闪存介质上的擦除周期。
  • 与此同时,这个主题已经作为一个错误进入“truncate” linux 手册页。我相信有一天它会在我第一次提出要求 20 年后实施
  • 同样的问题:stackoverflow.com/questions/339483/… 虽然在这里更明确

标签: filesystems


【解决方案1】:

在前面截断文件似乎不太难在系统级别实现。

但也有问题。

  • 第一个是在编程级别。在随机访问中打开文件时,当前的范例是使用文件开头的偏移量来指出文件中的不同位置。如果我们在文件开头截断(或从文件中间执行插入或删除),这不再是一个稳定的属性。 (虽然从末尾追加或截断不是问题)。

换句话说,截断开头会改变唯一的参考点,这很糟糕。

  • 正如您所指出的,存在系统级别的使用,但很少见。我相信文件的大多数用途都是一次写入多次读取,因此即使截断也不是一个关键功能,我们可能没有它可以做到(有些事情会变得更加困难,但没有什么是不可能的)。

如果我们想要更复杂的访问(确实有需要),我们以随机模式打开文件并添加一些内部数据结构。这些信息也可以在多个文件之间共享。这将我们引向我看到的最后一个问题,可能是最重要的问题。

  • 从某种意义上说,当我们使用具有某些内部结构的随机访问文件时……我们仍在使用文件,但我们不再使用文件范例。典型的此类情况是我们想要执行插入或删除记录而不关心它们的物理位置的数据库。数据库可以使用文件作为低级实现,但出于优化目的,一些数据库编辑器选择完全绕过文件系统(想想 Oracle 分区)。

我认为没有任何技术原因导致我们无法完成当前在操作系统中使用数据库作为数据存储层的文件完成的所有工作。我什至听说 NTFS 在其内部与数据库有许多共同点。操作系统可以(并且可能在不久的将来)使用另一种范式而不是文件范式。

总的来说,我认为这根本不是技术问题,只是范式的改变,删除开头绝对不是当前“文件范式”的一部分,但不是一个大而有用的改变,足以迫使改变任何东西.

【讨论】:

    【解决方案2】:

    可以分两步实现这个目标

    long fileLength; //file total length
    long reserveLength; //reserve length until the file ending
    int fd; //file open for read & write
    
    sendfile(fd, fd, fileLength-reserveLength, reserveLength);
    ftruncate(fd, reserveLength);
    

    【讨论】:

      【解决方案3】:

      在支持稀疏文件的文件系统上“打孔”并删除任意文件位置的数据非常容易。操作系统只需要将相应的块标记为“未分配”。从文件开头删除数据只是此操作的一个特例。主要需要一个系统调用来实现这样的操作:ftruncate2(int fd, off_t offset, size_t count)。

      在 Linux 系统上,这实际上是通过 fallocate 系统调用实现的,通过指定 FALLOC_FL_PUNCH_HOLE 标志将范围归零并指定 FALLOC_FL_COLLAPSE_RANGE 标志以完全删除该范围内的数据。请注意,可以指定的范围是有限制的,并且并非所有文件系统都支持这些操作。

      【讨论】:

      • 谢谢,我补充了。
      【解决方案4】:

      还有一个名为 head 的 unix 命令——因此您可以通过以下方式执行此操作:

      head -n1000 file > file_truncated
      

      【讨论】:

      • 重复答案,同tail +1000 > file_truncated
      【解决方案5】:

      NTFS 可以通过它的稀疏文件支持来做类似的事情,但它通常没那么有用。

      【讨论】:

        【解决方案6】:

        实际上有记录库文件系统——IBM 有一个,我相信 DEC VMS 也有这个功能。我似乎记得两者都允许(允许?我猜它们仍然存在)在文件中的随机位置删除和插入。

        【讨论】:

          【解决方案7】:

          我认为这里有一个先有鸡还是先有蛋的问题:因为文件系统没有有效地支持这种行为,人们还没有编写程序来使用它,并且因为人们没有编写程序来使用它它,文件系统几乎没有动力支持它。

          您始终可以编写自己的文件系统来执行此操作,或者修改现有的文件系统(尽管“在野外”使用的文件系统可能非常复杂,但从头开始可能会更容易)。如果人们发现它足够有用,它可能会流行;-)

          【讨论】:

            猜你喜欢
            • 2013-08-06
            • 1970-01-01
            • 2021-06-06
            • 2015-04-19
            • 1970-01-01
            • 2012-09-08
            • 2011-08-15
            • 2010-12-27
            • 1970-01-01
            相关资源
            最近更新 更多