稀疏文件

稀疏文件（）是一种计算机文件，它能尝试在文件内容大多为空时更有效率地使用文件系统的空间。它的原理是以简短的信息（元数据）表示空数据块，而不是在在磁盘上占用实际空间来存储空数据块。只有真实（非空）的数据块会按原样写入磁盘。

在读取稀疏文件时，文件系统会按元数据在运行时将这些透明转换为“真实”的数据块，即填充为零。应用程序不会察觉这个转换。

大多数现代的文件系统支持稀疏文件，包括大多数Unix变种和NTFS。苹果的HFS+不提供稀疏文件支持，但在OS X中，虛擬檔案系統层支持在任何受支持文件系统中存储稀疏文件，包括HFS+。2016年6月在WWDC宣布的苹果文件系统（APFS）支持稀疏文件。稀疏文件常被用在磁盘映像、数据库快照、日志文件和科学应用中。

 优势 
稀疏文件的优势是，它分配的存储空间只在需要时使用：这样节省了磁盘空间，并且可以创建很大的文件，即使文件系统中的可用空间不足。这也减少了首次写入的时间，因为系统不会分配“跳过”的空间。如果初始分配需要写入全零到空间，这也使得系统不必写入两次。

 缺点 
稀疏文件的缺点包括：稀疏文件可能碎片化；文件系统的空余空间报告可能产生误导；包含稀疏文件的文件系统被填满可能产生意外效果，例如只是重写现有文件的内容时遭遇磁盘已满或超出配额错误——开发者未预料到文件可能被稀疏；使用非显式支持的计算机程序复制稀疏文件可能会复制整个内容，即未压缩的文件大小，包括未实际在磁盘上分配的零空间——也就是使稀疏文件失去稀疏属性。稀疏文件也不是被所有备份软件和应用支持。不过，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选项。这尤为有用，如果一个已保存文件包含长串零块且非稀疏方式保存（即长串的零块已被完全写入并占用磁盘空间）。用此命令可以节省磁盘空间：
 cp --sparse=always file1 file1_sparsed
在某些例如FreeBSD的cp实现中，--sparse选项不被支持，将始终展开稀疏文件。这些系统上的可行替代方案是使用rsync的--sparse选项代替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。 
 参见 
 文件系统的对比

 参考资料 

 外部链接 
 NTFS Sparse Files For Programmers 
 Creating sparse files in Windows Server using fsutil 
 Creating sparse files in Solaris using mkfile(1M) 
 View the Size of the Sparse File of a Database Snapshot 
 SEEK_HOLE or FIEMAP: Detecting holes in sparse files 
 virtsync is a commercial solution to rsync's --sparse and --inplace issue.
 SparseChecker - Utility that allows to manage the sparse files on NTFS file system
 Phantom - a program to convert files to sparse files to reduce disk space 
 ArchLinux Wiki: Sparse file 
Category:计算机文件
Category:文件系统