稀疏文件(英語:sparse file)是一種計算機文件,它能嘗試在文件內容大多為空時更有效率地使用文件系統的空間。它的原理是以簡短的信息(元數據)表示空數據塊,而不是在在磁盤上占用實際空間來存儲空數據塊。只有真實(非空)的數據塊會按原樣寫入磁盤。

稀疏文件:空字節不需要保存,只需要通過元數據定義。

在讀取稀疏文件時,文件系統會按元數據在運行時將這些透明轉換為「真實」的數據塊,即填充為零。應用程序不會察覺這個轉換。

大多數現代的文件系統支持稀疏文件,包括大多數Unix變種和NTFS[1]蘋果的HFS+不提供稀疏文件支持,但在OS X中,虛擬檔案系統層支持在任何受支持文件系統中存儲稀疏文件,包括HFS+。2016年6月在WWDC宣布的蘋果文件系統(APFS[2])支持稀疏文件。稀疏文件常被用在磁盤映像數據庫快照、日誌文件和科學應用中。

優勢

編輯

稀疏文件的優勢是,它分配的存儲空間只在需要時使用:這樣節省了磁盤空間,並且可以創建很大的文件,即使文件系統中的可用空間不足。這也減少了首次寫入的時間,因為系統不會分配「跳過」的空間。如果初始分配需要寫入全零到空間,這也使得系統不必寫入兩次。

缺點

編輯

稀疏文件的缺點包括:稀疏文件可能碎片化;文件系統的空餘空間報告可能產生誤導;包含稀疏文件的文件系統被填滿可能產生意外效果,例如只是重寫現有文件的內容時遭遇磁盤已滿或超出配額錯誤——開發者未預料到文件可能被稀疏;使用非顯式支持的計算機程序複製稀疏文件可能會複製整個內容,即未壓縮的文件大小,包括未實際在磁盤上分配的零空間——也就是使稀疏文件失去稀疏屬性。稀疏文件也不是被所有備份軟件和應用支持。不過,VFS的實現迴避了先前兩個缺點。在Windows上加載稀疏的可執行文件(exe或dll)可能需要更多時間,因為文件不被映射到內存和緩存。

Unix中的稀疏文件

編輯

稀疏文件通常對用戶透明(不可見)處理。但在某些情況下,稀疏文件會與正常文件顯現出差異。

創建

編輯

Unix命令:

 dd of=sparse-file bs=1k seek=5120 count=0

將創建一個5MB大小的文件,但不在磁盤上存儲數據(僅存儲元數據)。(GNU dd也有此表現,因為它調用ftruncate來設置文件大小;其他實現可能是只創建一個空文件)。 如果truncate命令可用,也可以使用它:

 truncate -s 5M <filename>

刪除

編輯

ls命令的-s選項會以塊為單位顯示已占用的空間。

 ls -ls sparse-file

或者,du命令將打印占用的空間,而ls打印明面的大小。在一些非標準的du版本中,--block-size=1選項打印字節而非塊單位的占用空間,因而可以與ls的輸出比較:

 du --block-size=1 sparse-file
 ls -l sparse-file

複製

編輯

一般來說,GNU版本的cp是檢測文件是否為稀疏文件的較好方式,所以

cp sparse-file new-file

創建一個新文件,它將是稀疏性質。但是,GNU版本的cp有--sparse=WHEN選項。[3]這尤為有用,如果一個已保存文件包含長串零塊且非稀疏方式保存(即長串的零塊已被完全寫入並占用磁盤空間)。用此命令可以節省磁盤空間:

cp --sparse=always file1 file1_sparsed

在某些例如FreeBSD的cp實現中,--sparse選項不被支持,將始終展開稀疏文件。這些系統上的可行替代方案是使用rsync--sparse選項[4]代替cp。遺憾的是--sparse無法與--inplace組合使用,因此通過網絡rsync巨大文件時始終會浪費網絡和磁盤帶寬。

通過標準輸入

編輯
 cp --sparse=always /proc/self/fd/0 new-sparse-file < somefile

Windows的NTFS

編輯

如果一個文件的大部分數據是0,則這個文件被稱包含了稀疏數據集。 文件壓縮可以有效率地表示稀疏文件,但壓縮與解壓會帶來時間代價。 NTFS文件系統支持稀疏文件表示,並對文件的讀寫操作透明。

為確定文件系統是否支持稀疏文件,調用GetVolumeInformation函數,使用lpFileSystemFlags參數,檢查返回結果對應於FILE_SUPPORTS_SPARSE_FILES比特標誌。 DWORD dwFileSystemFlags = 0; BOOL bOk = GetVolumeInformation("C:\\", NULL, 0, NULL, NULL, &dwFileSystemFlags, NULL, 0); bOk = dwFileSystemFlags&FILE_SUPPORTS_SPARSE_FILES ; 判斷一個文件是否是稀疏文件:GetFileInformationByHandle

大部分文件,在改變它的EndOfFile的時候,中間的空白會被操作系統填0,也就是說,如果用SetFilePointer和SetEndOfFile來產生一個很大的文件,那麼這個文件它占用的是真正的磁盤空間,即使裡面全是0,系統默認的也會在DeviceIoControl()中的ControlCode里用FSCTL_SET_ZERO_DATA標記,這個標記使得那些文件空洞被0所填充。為了節省磁盤空間,必須把一個文件聲明為稀疏文件,以便讓系統把那些無用的0字節壓縮,並釋放相應的磁盤空間,這需要用DeviceIoControl()將標記改為FSCTL_SET_SPARSE。

參見

編輯

參考資料

編輯
  1. ^ Giampaolo, Dominic. Practical File System Design with the Be File System (PDF). Morgan Kaufmann Publishers. 1999 [2016-06-24]. ISBN 9781558604971. (原始內容 (PDF)存檔於2017-02-13). 
  2. ^ General Characteristics. Apple Inc. [2016-06-17]. (原始內容存檔於2016-06-13). 
  3. ^ Jim Meyering. GNU coreutils/cp: Accept new option, --sparse={never,auto,always}, to control creation of sparse files.. 1995-12-21 [2016-06-17]. 
  4. ^ Tridgell, Andrew. rsync: hard links, better sparse handling, FERROR and FINFO. 1996-06-29 [2016-06-17]. (原始內容存檔於2016-06-25). 

外部連結

編輯