如果我有一个包含许多零的大文件,如何有效地使其成为稀疏文件?
是否唯一可能读取整个文件(包括所有零,可能以稀疏方式存储)并使用 seek 跳过零区域将其重写为新文件?
或者是否有可能在现有文件中执行此操作(例如File.setSparse(long start, long end))?
我正在寻找 Java 或某些 Linux 命令的解决方案,文件系统将是 ext3 或类似版本。
8 年来发生了很多变化。
弗拉特
fallocate -d
filename
可用于在现有文件中打孔。从fallocate(1)
手册页:
-d, --dig-holes
Detect and dig holes. This makes the file sparse in-place,
without using extra disk space. The minimum size of the hole
depends on filesystem I/O block size (usually 4096 bytes).
Also, when using this option, --keep-size is implied. If no
range is specified by --offset and --length, then the entire
file is analyzed for holes.
You can think of this option as doing a "cp --sparse" and then
renaming the destination file to the original, without the
need for extra disk space.
See --punch-hole for a list of supported filesystems.
(该列表:)
Supported for XFS (since Linux 2.6.38), ext4 (since Linux
3.0), Btrfs (since Linux 3.7) and tmpfs (since Linux 3.5).
TMPFS在那个名单上是我觉得最有趣的一个。文件系统本身足够高效,只消耗存储其内容所需的 RAM,但使内容稀疏可能会进一步提高效率。
革奴cp
此外,在此过程中,GNU cp
对稀疏文件有了了解。引用cp(1)
手册页中关于其默认模式的内容,--sparse=auto
:
稀疏 SOURCE 文件由粗略的启发式方法检测,相应的 DEST 文件也变得稀疏。
但是还有 --sparse=always
,它激活了 fallocate -d
就地执行的操作等效的文件复制:
指定
--sparse=always
以在 SOURCE 文件包含足够长的零字节序列时创建稀疏 DEST 文件。
我终于能够停用我的tar cpSf - SOURCE | (cd DESTDIR && tar xpSf -)
单行代码,这是 20 年来我复制稀疏文件的灰胡子方式,并保留它们的稀疏性。
Linux/UNIX上的某些文件系统能够在现有文件中"打孔"。看:
- LKML 发布有关该功能的信息
- UNIX 文件整理常见问题解答(搜索F_FREESP)
它不是很可移植,也不是以同样的方式完成;截至目前,我相信Java的IO库没有为此提供接口。
如果通过fcntl(F_FREESP)
或任何其他机制可以打孔,它应该比复制/查找循环快得多。
我认为您最好预先分配整个文件并维护占用的页面/部分的表/位集。
使文件稀疏将导致这些部分在被重用时被碎片化。也许节省几 TB 的磁盘空间不值得高度碎片化的文件的性能下降。
您可以在 linux 终端上使用 $ truncate -s filename filesize
来创建具有
仅元数据。
注意 --文件大小以字节为单位。
根据这篇文章,除了使用 FIEMAP ioctl 之外,目前似乎没有简单的解决方案。但是,我不知道如何将"非稀疏"零块变成"稀疏"零块。