有许多类似的问题,但是在谷歌搜索之后没有任何具体的答案。这是:
假设我们有一个文件(可能是二进制文件,也可能更大):
abcdefghijklmnopqrztuvwxyz
C中最好的方法是将此文件的最右边部分“移动”到左侧,截断文件的开头..例如,“front truncating”7个字节会改变磁盘上的文件是:
hijklmnopqrztuvwxyz
我必须避免临时文件,并且不希望使用大缓冲区将整个文件读入内存。我想到的一种可能的方法是使用带有“rb +”标志的fopen,并且不断地来回读取和写入从offset开始复制字节,然后将setEndOfFile截断到最后。这似乎是很多寻求(可能效率低下)。
另一种方法是两次打开同一个文件,并将fgetc和fputc与相应的文件指针一起使用。这甚至可能吗?
如果还有其他方法,我很乐意阅读所有这些内容。
答案 0 :(得分:4)
您可以将mmap文件存入内存,然后记忆内容。您必须单独截断文件。
答案 1 :(得分:3)
你不必使用巨大的缓冲区大小,内核将为你做一些艰苦的工作,但是,从文件中读取一个缓冲区,然后写一个接近开头的方式就是这样如果你不能做更简单的工作来创建一个新文件,将你想要的东西复制到那个文件中,然后将新的(临时)文件复制到旧文件上,就可以做到这一点。我不排除将你想要的东西复制到一个新文件,然后移动新文件代替旧文件或复制旧文件的方法比你描述的洗牌过程更快的可能性。 。如果要删除的字节数是磁盘块大小而不是7个字节,则情况可能不同,但可能不同。唯一的缺点是复制方法需要更多的中间磁盘空间。
假设您使用POSIX系统,您的大纲方法将需要使用truncate()
或ftruncate()
将文件缩短到适当的长度。如果您没有truncate()
,则需要进行复制。
请注意,如果您在开始写作时小心不要破坏文件,请使用"r+b"
模式fopen()
或O_TRUNC
open()
1}}。
答案 2 :(得分:2)
如果您使用的是Linux,则从Kernel 3.15开始,您可以使用
#include <fcntl.h>
int fallocate(int fd, int mode, off_t offset, off_t len);
带有FALLOC_FL_COLLAPSE_RANGE
标志。
http://manpages.ubuntu.com/manpages/disco/en/man2/fallocate.2.html
请注意,并非所有文件系统都支持它,但大多数现代文件系统(例如ext4和xfs)都支持。