文件的打包、压缩与解压缩是经常会使用到的功能,我们可以通过 tar、gzip 等工具来完成这些操作。在 Go 中,标准库archive与compress为我们提供了这些能力,通过本文示例,你会发现以 Go 编程的方式生成与处理压缩打包文件也非常简单。

打包和压缩

打包和压缩

在开始代码之前,我们需要明确打包和压缩的概念。

  • 打包,又被称为归档,指的是一个文件或目录的集合,而这个集合被存储在一个文件中。
  • 压缩,指的是利用算法将文件进行处理,以达到保留最大文件信息,而让文件体积变小的目的。

以打包工具 tar 为例,通过其打出来的文件通常称为 tar 包,其文件命名通常以 .tar 结尾。再通过其他的压缩工具对 tar 包进行压缩,例如 gzip 压缩,则得到通常以 .tar.gz 结尾命名的压缩文件(在 tar 中可使用 -z 参数来调用gzip)。

tar 包是文件的集合,其结构也是由数据段组成的,每块数据段包含了文件头(描述文件的元信息)和文件内容。

archive 库打包与解包

archive 库打包与解包

archive 库的中文含义是档案,它的作用就是归档(打包)与拆档(解包)。其提供两种方案:tar 与 zip,调用路径分别为archive/tar和archive/zip。

我们以 tar 为例,来展示如何实现文件的打包与解包。

首先,新建目标打包文件为 out.tar,再构造一些文件数据 readme.txt、gopher.txt 和 todo.txt 用于归档。

接着依次构建文件头信息,分别指定了文件名、权限和大小(可定义更多文件头字段),再通过*tar.Writer类型的 tw 变量,按序调用WriteHeader和Write方法将需要打包的数据段(文件头+文件内容)写入到out.tar文件。

执行以上代码,将得到打包后的 out.tar 文件,可通过 tar 工具指定 -tvf 参数查看归档信息。

可以看到,指定的文件信息(文件名、权限和大小)符合预期,但其他未指定的元信息是有误的,例如日期(直接给的默认值)。

如果通过 tar 工具,我们可以执行以下命令来提取 out.tar 中的文件。

但在程序中实现,应该怎么做呢?

首先需要打开 out.tar,并构造*tar.Reader类型的 tr 变量。之后,利用tr.Next依次提取每个数据段内容,并通过 io.Copy(os.Stdout, tr),将文件内容拷贝至标准输出。直到tr.Next遇到io.EOF,它代表读取到了归档文件末尾,则退出提取。

compress 库压缩与解压缩

compress 库压缩与解压缩

compress 库中支持了多种压缩方案,包括 bzip2、flate、gzip、lzw 和 zlib,调用路径为compress/xxx。

我们以常用的 gzip 为例,来展示压缩与解压缩代码。

如果同样是上文中的文件数据 readme.txt、gopher.txt 和 todo.txt,我们想得到 tar 归档且被压缩了的 out.tar.gz 文件,应该如何做呢?

非常简单!只需要将tar.NewWriter(tarFile)改为tar.NewWriter(gz)即可,其中gz是由 gzip.NewWriter(tarFile)而来。

我们比较有压缩与无压缩的归档 tar 包大小,可以看到文件体积从4.0K压缩为了224B。

同理,如果要解压并解包 out.tar.gz 文件,应该如何做呢?

总结

总结

注:文章转自Golang技术分享,侵删