5.11 压缩和解压缩

压缩和解压工具是计算机文件管理中的基础工具。数据压缩利用信息的统计冗余性,通过编码算法减少数据表示所需的存储空间。根据是否允许信息丢失,压缩算法可分为无损压缩(lossless compression)和有损压缩(lossy compression)两大类。本节所涉及的工具均采用无损压缩算法,即解压后的数据与原始数据完全一致。

常见的无损压缩算法及其特征如下:

算法
所用格式
技术基础
特点

DEFLATE

zip/gzip

LZ77 + Huffman 编码

经典通用

LZMA/LZMA2

xz

LZMA 链式压缩

高压缩率

LZ4

lz4

字节级 LZ77

极高速度

Zstandard

zstd

有限状态熵 + LZ77

兼顾速度与压缩率

bzip2

bz2

Burrows-Wheeler 变换 + Huffman

较高压缩率,速度较慢

zip

zip 格式是 PKZIP 归档格式的实现,其规范由 PKWARE 维护(APPNOTE.TXT),Info-ZIP 项目提供了开源的 zip/unzip 工具实现。zip 是一款压缩和文件打包工具,兼容 PKZIP(Phil Katz 的 ZIP for MSDOS 系统),zip 3.0 版本兼容 PKZIP 2.04 并支持 Zip64 扩展(允许归档和文件超过 2 GB 限制)。zip 使用 deflation 作为默认压缩方法,也可存储不压缩的文件,并自动为每个文件选择更优的方式。

zip 格式是 Windows 上最常用的格式,但对 Unicode 文件名支持有限(取决于 zip 工具版本和压缩设置)。在跨平台交换文件时建议使用 tar.xz 或 tar.zst 格式。

技巧

在使用 zip 压缩中文或非英文字符时出现乱码是正常现象。由于编码方式不同,zip 3.0 在支持 Unicode 的平台上编译时,会额外存储路径的 UTF-8 翻译,以改善跨平台文件名兼容性。解压时可使用 unzip -O 选项指定文件名编码(如 unzip -O GBK),或使用 convmv 批量转换已解压的乱码文件名。

安装 zip

  • 使用 pkg

# pkg install zip
  • 使用 Ports

# cd /usr/ports/archivers/zip/
# make install clean

zip 压缩

zip 解压

zip 文件解压时,需要安装 unzip 工具(FreeBSD 基本系统自带的 bsdunzip 基于 libarchive,功能有限;如需完整功能,可通过 pkg install unzip 安装 Info-ZIP 版本)。

unzip 的 -d 选项后面跟目录名,可以有空格(如 -d /path),也可以紧贴(如 -d/path)。

tar

基本系统自带 tar,无需安装。

tar 是“tape archive”(磁带归档)的缩写,最初用于在磁带上进行文件存储。FreeBSD 的 tar 实现基于 libarchive 库(即 bsdtar),替代了早期版本中的 GNU tar。该实现可从 tar、pax、cpio、zip、jar、ar、xar、rar(包括 RAR2、RAR3 及大部分 RAR5 格式,仅限读取,受专有格式限制)、rpm、7-zip 及 ISO 9660 光盘镜像中提取文件,并可创建 tar、pax、cpio、ar、zip、7-zip 和 shar 格式的归档。

GNU tar 支持自动识别多种压缩格式;bsdtar 在解压时同样会自动检测压缩格式(无需手动指定 -z-j-J 等选项),并支持从 tar、pax、cpio、zip 等多种格式中提取,GNU tar 仅支持 tar 相关格式。

思考题

归档文件包是指压缩率为 0 的文件集合,即将多个文件或目录打包成单一文件以便存储。单纯使用 tar 只打包而不压缩。压缩的本质是通过算法减小文件占用的存储空间,而非针对目录本身。因此,常见压缩软件通常先将目录归档为文件,随后再压缩。

如何理解归档与压缩的关系?

tar 压缩

tar 解压

选项说明:

选项
含义

x

Extract,解压

v

verbose,输出详细信息模式

f

file,指定文件

C

即 cd,指定路径

xz

基本系统自带 xzunxz,同样无需安装。xz 格式是当前压缩率最高的格式之一,特别适合大文件归档。

xz 压缩

默认压缩后会删除原文件,建议加 -k 选项保留原文件。

压缩并删除原文件:

unxz 解压

unxz 实际上是 xz 的硬链接,使用 xz -d 或直接 unxz 效果相同。

7z

7z 格式具有极高的压缩率,特别适合大文件归档。

在 FreeBSD 操作系统中,7z 命令可通过安装 archivers/7-zip 包使用。

安装 7-zip

  • 使用 pkg:

  • 通过 Ports:

7z 压缩

a 表示 add,将要压缩的文件添加到 test.7z。

7z 解压

-o 即 Output,指定输出路径。

警告

-o/home/ykla/下载/test-o 与路径之间 不能有空格,这并非拼写错误,而是 7z 命令的设计方式。欢迎提交 PR 改进。

rar

rar 是 Windows 上最流行的格式之一,但在 Unix 世界使用率较低;rar 有较好的恢复记录和分卷功能,适合大文件传输。

rar 格式是专有格式,未在基本系统内置。

安装 rar

  • 通过 pkg 安装:

  • 通过 Ports:

rar 压缩

a 表示 add(添加),将文件添加到 archive.rar

rar 解压

zstd

zstd 是 Meta(原 Facebook)开发的快速压缩算法,兼顾压缩速度和压缩率,是现代系统首选的压缩格式。

zstd 也是基本系统内置的压缩工具,zstd 支持多种预设级别,从最快(-1)到极限压缩(--ultra -22)。

zstd 压缩

  • 使用 zstd 压缩单个文件

  • 使用 zstd 压缩文件夹。

zstd 不直接支持压缩文件夹(参见:GitHub. How can I compress a directory?[EB/OL]. [2026-03-26]. https://github.com/facebook/zstd/issues/1526.)。该 Issue 讨论了 zstd 不支持直接压缩目录的技术原因与替代方案,因此需要先将文件夹打包为 tar 文件。

思考题

zstd 为什么不支持压缩文件夹?有哪些可能性?

test.tar 压缩成 test.tar.zst

此外,也可直接使用 tar 的 --zstd 选项一步完成打包与压缩:

示例:

查看结果:

文件结构图:

zstd 解压

解压到当前路径

技巧

这样解压出来的是 test.tar,还需要再用 tar 解压一次。

解压到指定路径

技巧

同上,解压出来的是 test.tar,还需要再用 tar 解压一次。

课后习题

  1. 使用 zip、tar、xz、7z、rar、zstd 等工具分别压缩和解压包含中文文件名的文件,对比各工具对 UTF-8 编码的处理方式,分析不同压缩格式在国际化支持上的设计差异。

  2. 使用不同压缩算法(gzip、bzip2、xz、zstd)压缩同一组文件,对比压缩率、压缩时间和解压时间,分析各算法在压缩效率与计算性能之间的权衡策略。

  3. 查阅 zip 格式规范中关于文件名编码的条款,分析中文文件名乱码问题的根源,评估现有补丁方案的适用范围。

最后更新于