压缩格式文件与 NTFS 中的“压缩”

文:Masaki

在某个 QQ 群中,有人问我这样一个问题,ZIP 压缩文件和 NTFS 中的“压缩”的压缩比的问题。很显然,这个问题涉及到压缩的方式与算法问题。一般说来,被压缩过后的文件在 NTFS 的再压缩存储后,文件的大小是不变的。而有时候,也有少部分的压缩文件的“占用空间”会比文件的实际大小少几百个字节。而这个问题的背后,其实是存在着这样一个问题,那就是——我想节约我的硬盘空间的开支,在使用 NTFS 的“压缩”特性和如“ZIP”、“RAR”等常用压缩文件格式间,我应该如何选择。

先看几张关于磁盘占用空间大小的图片。

ntfs_org5b45d
这是未作任何压缩的文件夹——内容不用介绍了吧?Sysinternals 的 Process Explorer。

zip5b45d
这个是 ZIP 格式压缩的前一个文件夹后的 ZIP 压缩文件。

ntfs_zip5b45d
这个是使用 NTFS 压缩后的文件夹属性,占用空间就比文件实际大小要小了。

那么,接下来就有一个问题需要考虑了。你想要压缩的文件,是需要频繁使用的吗?还是使用率并不是太频繁的呢?

好,我们就带着这样的问题来一起认识这两种不同的压缩方法的基础技术说明吧。

先来说一下压缩格式方面的压缩。我们常见的压缩文件通常有前面说到的 *.ZIP、*.RAR,还有 *.CAB、*.7Z 等格式。这类压缩格式通常是一种“归档(打包)”类的格式,也就是把所有的被压缩文件打包存在一起。采用如 Deflate、LZMA 的字典编码的算法进行文件压缩,还有如“固实压缩”的把所有被压缩文件视为一个被压缩的整体,以达到更大的压缩率。到这里,其实已经基本可以看得出来,压缩格式文件的几个特性:

  1. 采用不同的压缩算法进行压缩文件。同一种压缩文件格式可能会采用多种不同的压缩算法。
  2. 不同的压缩算法,所需的压缩(编码)与解压缩(解码)的时间不同。
  3. 被压缩的文件是被存放在新的存放容器(压缩文件)中的。

上述的一些压缩算法,可以登录 Wikipedia.org 查找到他们的一些基本信息。

而在 NTFS 下的“压缩”属性中,由于这里的使用平台是文件系统级别的,因此不能与压缩文件格式那样,把整个分区或者是一个文件夹压缩成一个“包”,这样会对一些大型文件的处理带来麻烦——首先,你要恢复文件到非被压缩编码的状态,然后才可以对文件进行进一步的访问操作。这样的话,十几 MB 的文件可能还行,如果是上百 MB、上 GB 的文件的话,必然让你只能花大段的时间等下去。那么,到这里就可以基本能够看得出来,NTFS 的压缩的目的是——既要节省硬盘空间,又要能够快速读写数据。所以 NTFS 的“压缩”对于文件数据其实是采用以下两种方式的:

压缩稀疏数据

稀疏数据通常是很大的文件,但是总体来说,他只有少部分的非零数据。所谓“零数据”,就是指那一段的数据为空,比如现在很多的 P2P 软件的设置中,你都可以看到如“将下载的文件以稀疏数据方式存放(仅 NTFS)”。通常说来,如果你是刚建立的这样的一个任务,你在查看该文件的属性时,文件大小是正确的,而占用空间上,如果文件被压缩了的话,可能占用空间只有“0 字节”,或者是其他的极小的数值。似乎,我应该还要把 NTFS 的 MFT 的概念稍微带一下。“MFT”是指“主文件表”,这个表就是类似于一本书中的目录,在以前的 FAT 系统中,虽然也有一份这样的目录,但是,他只是告诉你这份文件的开始位置,中间的“排版(硬盘上的物理存储位置)”的不连贯的“下一页”的位置是在文件中说明的,就像我们现在还有很多杂志、书刊在放不下位置的时候,会在那页末尾加上“下转第 X 页”一样。如果,老是有这样的下转(真有这样的书估计就没人看了),你会不会因为要找到你要的那部分的数据而来回在书中翻来翻去?这时,是否会想,要是在目录中直接告诉我那些页是就可以了。而,NTFS 的这个文件分配表就可以做得到。接下来,我们应该还需要了解两个名词——“VCN”和“LCN”。VCN 的全称是“Virtual cluster number”,虚拟簇编号的意思,LCN 应该有人能够就猜着了——Logical cluster number,逻辑簇编号。简单来说,VCN 是指文件的数据排列顺序位置,而 LCN 是指文件在磁盘上的物理逻辑位置。而 VCN 和 LCN 都是记录在 MFT 中的,如果在 MFT 中,系统如果发现 LCN 和 LCN 所记录的簇数目相等,那么这个文件数据实际上是未被压缩的。虽然也可能是被标记为“压缩”属性。如果簇数目不相等的话,那么数据是被压缩的。

回过头来说稀疏文件。比如这一个 BT 下载文件(稀疏化保存),最前面的数据已经下载好了,中间是空的,文件末尾也已经下载好了,那么他的正常数据应该是连续的。在压缩后,凡是使用二进制编辑器打开后,显示数据为“00”的数据,一律在 LCN 上跳过不写入,我们可以看一张图来了解一下。

e7a880e7968f5b165d

在图中,原始未压缩数据中的中间部分假定为空数据,那么,在实际写入过程中,这一部分的数据就省略了。在图中,就节省了 16 个簇空间。在读取文件时,系统也会根据 MFT 的记录判断,如果 VCN 的编号不连贯,在中间的簇数据在读取时自动用二进制“00”填充。这样就与原始数据相一致了。那有人会说了,这样文件下载完了,实际的硬盘上的位置不是很乱了吗?不会造成文件读写变慢吗?你还记得我刚才提到的“目录”吗?何况,就算是预先把空间分配了,除了基本全空的分区,其他稍微大点的文件基本不存在连续的簇存放。所以,这点就不用担心了吧。

那么另一个是非稀疏数据压缩。

NTFS 的非稀疏数据的压缩是以一定的单元空间(16 簇),只要能够节约出一定的空间(1 个簇),那么,系统就会对这部分数据进行压缩(通过 LZ77 算法)写入数据。我们继续用一张图来做简单的解释。

e695b0e68dae5b115d

在图中,VCN 17~32 的数据是没有被压缩的,原理已经在上面说过。而 VCN 0~16(实际写入 21~30 的 9 个簇)和 33~48(实际写入 48~54 的 6 个簇)是被压缩过了的。这样,原本需要 48 个簇的数据就可以以 33 个簇搞定,节省 15 个簇的空间。这样压缩后的特点就是,LCN 的编号就与 VCN 的编号不对称了。那么在读取的时候,系统在读取 MFT 的记录时,发现统一段落的 LCN 记录比 VCN 记录小,那么,系统就会以解压缩的方式读取文件。

最后来做一些总结,来比较的全面对压缩文件格式技术和 NTFS 使用的“压缩”技术,可以把一开始不能都直接拿出来对比的东西都可以排列出来了。

NTFS 的“压缩” 压缩文件格式
压缩后文件存在方式 以原始格式单个文件形式存在 改变文件格式,可以多个文件归档为单个压缩包,也可以单个文件单个压缩包
压缩编码可选择性 不可选择。仅压缩稀疏数据和 LZ77 编码两种 视压缩程序而定。
基本可选择多种的压缩编码器或其他压缩格式。
压缩度可选择性 不可选 视压缩程序而定。普通压缩或最大压缩等,还有一些提供“固实”压缩(单个归档文件中,不同文件中的相同数据只存一次)
编/解压缩速度 相对较快 视压缩度而定。使用“最大压缩”和“最小压缩”相比会有很大的时间差
压缩率 一般 视压缩度而定。
打开/再处理文件便捷性 方便,可直接访问数据 必须从归档的压缩包中做解压处理,极少数格式支持直接读取,但修改或写入必须重新创建压缩包。

这个表格可能会有一些可对比的东西会被我忽略——基本上是无意的,因为,我在写这段话的时候,还没想到还能比其他什么。不过,大致这两种方式的压缩的特点都已经谈到了。

那么,回到文章最先的那个问题中来——“我想节约我的硬盘空间的开支,在使用 NTFS 的“压缩”特性和如“ZIP”、“RAR”等常用压缩文件格式间,我应该如何选择。”

如果,你的文件要频繁使用的,那么就使用 NTFS 的压缩吧。它对你使用数据所带来的压缩、解压缩需要的处理时间绝对是你可以接受的——体感速度不会太慢。

如果是长时间不用的——ZIP、RAR、7Z 等等都是一个好的选择,实际上在使用 Windows 自带的“磁盘清理程序”中的“长期不访问的旧文件”的处理方式也是打包归档处理。不过,就是你如果要再次使用的话,还是要准备好文件解压后大小的磁盘空间哦!如果,你不介意的话,可以把文件转移到光盘(烧录)、其他外接的如移动硬盘、U 盘等等设备上,那样有时会更方便。
——————————————————————————————————
参考资料:

  • 《深入解析 Windows 操作系统》,第四版。 [美]Mark E. Russinovich、[美]David A. Solomon 著,潘爱民 译。 电子工业出版社。
  • NTFS”,维基百科
  • ZIP (文件格式)”,维基百科
  • RAR”,维基百科
  • Deflate”,维基百科
  • 压缩软件比较”,维基百科

注:来自维基百科的资料参考包含但不限于“中文”语种。