標籤:

C / C++,怎麼高效地刪除文件中的前100個位元組?

類似問題:

Truncating the first 100MB of a file in linuxstackoverflow.com圖標

不過我的環境較舊,不支持該 fallocate 操作:

操作系統 內核:3.10.0-514.el7.x86_64

文件系統:xfs | ext4

C++98


從第101個位元組開始複製到另一個新文件,刪除原文件,把新文件rename


刪除 100 位元組的話,估計沒有高效的辦法,因為文件系統不支持。


dd if=infile of=outfile bs=100 skip=1

or

fd=open(file(

ptr=mmap(fd)

memcpy(ptr,ptr+100,file_length)


高效的辦法,當然是修改文件的元數據了,將文件的起始往位置往前挪100個位元組,然後把文件的長度減少100位元組。

但是Linux的VFS根據不提供這樣的介面,類似的介面只有ftruncate做截斷和fallocate做預分配,所以在現有的VFS介面上是完成不了這樣功能的。有回答提到根據FAT文系統格式修改元數據的方法,這種方法就不是利用OS的文件操作功能來完成了,而是自己寫了一個簡單的文件系統實現。而且你這個文件系統實現,無法跟OS的文件系統互斥,並發訪問,會出現邏輯問題。

那隻能採用退而求其次的辦法,@姚冬 提到的文件拷貝,也有回答提到dd命令,原理也是一樣的。


如果文件是你自己用,那就自己騙自己了,每次open後先定位到100偏移:)


我告訴你一個骨骼清奇的辦法。

1、獲取文件長度orig_len

2、原始長度減去100得到新長度值new_len = orig_len - 100

3、按照每次讀寫N個位元組的辦法,從第101位元組開始,寫到前面N節的位置。如此反覆之後從101位元組開始的內容就全部往前挪動了。N的大小由你自己來確定,最好是4096的倍數。

4、最後調用ftruncate(fd,new_len)截斷文件長度。


如果是大量文件可以編寫一個簡單的基於 fuse 的虛擬文件系統,對特定目錄或文件的訪問,自動偏移到指定位元組,這樣上層程序可以不用動,原始文件也不用動


文件分塊來存儲,如果可以把文件起始塊的內容改掉,並且將塊大小變小,應該就可以實現快速刪起始數據了,但不知道ext4和xfs支不支持。。哈

當然,如果文件大小只有100位元組,那隻需設一下文件大小為0就完事了。


讀取的時候跳過100個位元組。


一般需要做編輯操作的文件都不會很大,而且大多是文本文件,我一般是讀出來處理好,把源文件清空,重新寫入。


系統沒給這樣的api,只能向後複製


system("tail -c +101 SRCFILE > DSTFILE");


不了解linux的操作,不過可以發散下。這裡的名詞術語可能不對,因為我也記不清了。以FAT文件系統為例,FAT表裡每一項都級連著下一項,每一項存著一個扇區號,那麼刪前一百個位元組,可以找到第一塊扇區對應的頁表項,然後拷貝走去掉前一百個位元組的數據到新扇區,然後再修改第一塊扇區頁表指向新的扇區號。這樣前一百位元組就刪除了。可能細節有問題,但大體上就是這個意思。然後你找linux里是否有哪個操作內部是這麼實現的就可以了。


推薦閱讀:

EE小碩在讀,求Coursera課程推薦?
為什麼說Arch Linux的pacman包管理系統更先進?相比與apt或rpm等好在哪裡呢?
用作生產環境伺服器,FreeBSD和CentOS相比有哪些優劣勢?
工業中為什麼很少採用 Linux 伺服器?

TAG:編程 | Linux | CC |