【问题标题】:How to cut a file without using another file?如何在不使用另一个文件的情况下剪切一个文件?
【发布时间】:2012-08-31 22:06:32
【问题描述】:

是否可以删除文件的一部分(比如说从头到尾),而不必使用另一个文件?

谢谢!

【问题讨论】:

  • 您接受使用 RAM 吗?我可以在内存中读取 0.5 个空洞文件,删除它,然后再写入 0.5 个我读过的数据。
  • 我认为这是 OP 试图避免的。
  • 简短回答:不,(至少大多数)文件系统不支持。您所能做的就是创建一个副本(在相同或不同的文件中),去掉不需要的部分。
  • @JerryCoffin:如果您将其写在答案中,我会将其标记为已接受。

标签: c++ logging stl fstream


【解决方案1】:

是的,这是可能的,但您仍然必须重写大部分文件。

大致思路如下:

open the file
beg = find the start of the fragment to be removed
len = length of the fragment to be removed
blocksize = 4096 -- example block size, may be any
datamoved = 0
do {
  fseek(pos +len +datamoved);
  if( endoffile ) return; -- finished!
  actualread = fread(buffer, blocksize)
  fseek(pos + datamoved)
  fwrite(buffer, actualread)
  datamoved += actualread
}

循环之后的最后一步是将文件“截断”为 pos+datamoved 大小。如果底层文件系统不处理'truncatefile'操作,那么你必须重写..但大多数文件系统和库都支持。

【讨论】:

  • 仅供参考:在传统 HDD 或软盘或 ZIP 驱动器等上,以这种方式删除文件片段可能比将文件重写到新文件要慢得多,因为回溯写入可能会导致驱动器的磁头到,好吧,寻求:) 可能,但不必。此外,如果您可以将代码绑定到特定的文件系统,您可能会发现一些低级操作实际上可以从文件中间插入/重新排序/删除 BLOCK/INODE - 然后您只需移动少量数据,但执行起来相当复杂..
【解决方案2】:

简短的回答是不,大多数文件系统不尝试支持这样的操作。

这让您有两个选择。显而易见的一个是创建数据的副本,省略您不想要的部分。您可以就地执行此操作(即,在同一个文件中移动数据)或使用辅助文件,通常将数据复制到新文件,然后执行类似将新文件重命名为旧名称的操作。

另一个主要选择是简单地重新构建您的文件和数据,这样您就不必完全摆脱旧数据。例如,如果您想保留进程中最近的 N 数据量,您可以将文件(大部分)构造为循环缓冲区,在开头有几个“指针”告诉您头和尾点,所以你知道从哪里读取数据/向哪里写入数据。使用这样的结构,您不会擦除或删除旧数据,只需根据需要覆盖它即可。

【讨论】:

    【解决方案3】:

    如果你有足够的内存,将其内容完全读入内存,将其复制回文件的前面,然后截断文件。

    如果您没有足够的内存,请以块为单位进行复制,并且仅在您完成后截断文件。

    【讨论】:

    • 但是文件可能太大而无法在内存中复制,即使阻塞需要很长时间
    • 读入块内存不是问题。时间问题不在于内存,而在于 I/O - 文件越大,进程越长。
    猜你喜欢
    • 2014-07-06
    • 2013-08-13
    • 2017-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-24
    相关资源
    最近更新 更多