在前面截断文件

7 浏览
0 Comments

在前面截断文件

最近我正在处理一个问题,这让我希望能够截取文件的前部分。有点像“从前截断”,如果你愿意这样说的话。在文件末尾截断是常见的操作-我们做得很自然。但在文件的前面截断呢?一开始听起来很荒谬,只是因为我们被训练成认为这是不可能的。但是在某些情况下,截断操作可能会很有用。\n一个简单的例子(当然不是唯一的,也不一定是最好的例子)是FIFO队列。您将新项目添加到文件的末尾,并从文件的前面提取项目。随着时间的推移,文件会不断增长,并且在前面有一个巨大的空白空间。在当前文件系统中,有几种解决这个问题的方法:\n

    \n

  • 当每个项目被移除时,将剩余的项目复制并替换它,然后截断文件。虽然这样可以工作,但是这种解决方案非常耗时。
  • \n

  • 监视文件前面的空白空间的大小,当它达到特定的大小或整个文件大小的百分比时,将所有内容向上移动并截断文件。这比前一个解决方案更有效,但是移动文件中的项目仍然需要时间。
  • \n

  • 在文件中实现一个循环队列,将新项目添加到文件前面的空洞中,当项目被移除时。这可以非常高效,尤其是如果您不介意队列中的顺序可能被打乱的话。如果您关心顺序,可能需要移动项目的可能性。但是循环队列非常容易实现,并且可以有效管理磁盘空间。
  • \n

\n但是,如果有一个截断操作,从队列中删除一个项目将变得与截断文件一样简单。实际上,与截断文件一样简单。那么,为什么没有这样的操作呢?\n我对文件系统的实现有一些了解,我没有看到任何特别困难的原因。在我看来,它似乎只需要每个分配条目额外的一个字(例如双字?)来指示文件在块内的起始位置。随着100美元以下购买1TB的硬盘,为这样的功能付出这样的代价似乎是微不足道的。\n如果您能像截断文件末尾一样高效地截断文件的前面,还有哪些任务会变得更容易?\n您能想到为什么这个功能不能添加到现代文件系统中的任何技术原因吗?其他非技术原因呢?

0
0 Comments

原因:NTFS文件系统可以通过其稀疏文件支持来实现截断文件的功能,但一般情况下并不常用。

解决方法:可以使用以下代码来实现截断文件的功能。

import os
def truncate_file(file_path, size):
    with open(file_path, 'rb+') as file:
        file.seek(size)
        file.truncate()
# Usage example
truncate_file('example.txt', 1024)

这段代码打开指定文件,然后将文件指针移动到要截断的位置,并使用`truncate()`方法将文件截断为指定大小。在上面的示例中,文件`example.txt`将被截断为1024字节。

请注意,这段代码只适用于Python编程语言。如果您在使用其他编程语言,可能需要根据具体语言的文件操作功能来实现截断文件的操作。

0
0 Comments

原因:在系统级别上,从文件前面截断文件似乎并不难实现,但存在以下问题:

1. 在编程级别上,当使用随机访问打开文件时,当前的范式是使用相对于文件开头的偏移量来指出文件中不同位置。如果我们在文件开头进行截断(或在文件中间进行插入或删除),这个偏移量就不再是一个稳定的属性了。换句话说,截断文件的开头将改变唯一的参考点,这是不好的。

2. 在系统级别上,使用截断功能的情况并不常见。我相信大多数文件的使用是一次写入多次读取的类型,因此即使没有截断这个功能,我们可能也可以应付(虽然有些事情可能会变得更困难,但没有什么是不可能的)。

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

在某种意义上,当我们使用带有一些内部结构的随机访问文件时...我们仍然在使用文件,但不再使用文件的范式。典型的例子是数据库,我们希望在不关心物理位置的情况下执行记录的插入或删除。数据库可以使用文件作为底层实现,但为了优化的目的,一些数据库编辑器选择完全绕过文件系统(考虑Oracle分区)。

解决方法:我认为从技术上讲,我们完全可以使用数据库作为数据存储层来执行操作系统中目前使用文件进行的所有操作。我甚至听说NTFS在其内部与数据库有很多共同点。一个操作系统可以(并且可能在不太遥远的将来会)使用与文件不同的范式。总之,我认为这不是一个技术问题,而是一个范式的改变,从而从当前的“文件范式”中去除开头截断并不是一个重大且实用的变化,无需改变任何东西。

0
0 Comments

在支持稀疏文件的文件系统上,通过“戳洞”和删除文件中的数据非常容易。操作系统只需将相应的块标记为“未分配”。从文件开头删除数据仅是此操作的一个特殊情况。唯一需要的是实现此操作的系统调用:ftruncate2(int fd, off_t offset, size_t count)。

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

谢谢,我已经添加了这个信息。

原因:在支持稀疏文件的文件系统上,可以通过标记相应块为“未分配”来实现戳洞和删除文件中的数据。从文件开头删除数据只是这一操作的特殊情况。需要一个系统调用来实现这一操作。

解决方法:在Linux系统上,可以使用fallocate系统调用来实现这一操作。通过指定FALLOC_FL_PUNCH_HOLE标志来清空一个范围,并通过指定FALLOC_FL_COLLAPSE_RANGE标志来完全删除该范围内的数据。请注意,对可以指定的范围有限制,并且并非所有文件系统都支持这些操作。

0