Golang 实现文件 tar/tar.gz 压缩与解压操作指南

小石头
小石头
发布时间:2026-10-16 | 7人浏览过
原创

在 Go 语言中处理归档文件主要依赖标准库 archive/tar。本文详解如何使用该库结合 bytes.Buffer 或 os.File,实现将多个文件或字符串内容压缩为 .tar/.tar.gz 格式,以及如何解析压缩包并还原内容。涵盖核心的写入头信息、写入数据及关闭 Writer 的关键步骤。

使用 Tar 压缩文件并保存为 .tar.gz

实际开发中,通常需要将多个文件打包并保存为磁盘上的压缩文件(如 .tar.gz)。虽然 Gzip 压缩由 compress/gzip 处理,但基础的 .tar 归档仅使用 archive/tar 即可生成未压缩的包;若需 gzip 压缩,需配合 Gzip Writer。以下演示基础 Tar 归档逻辑,并通过 os 库将缓冲区内容写入文件。

第1步:初始化压缩写入器

创建一个 bytes.Buffer 作为临时缓冲区,使用 tar.NewWriter 包装它。该 Buffer 用于暂存压缩数据,后续可写入文件或通过网络发送。

第2步:构建 Tar Header 并写入文件元数据

遍历待压缩的文件列表。对每个文件创建 tar.Header,设置文件名(Name)、权限(Mode)和大小(Size)。调用 tw.WriteHeader 将头部信息写入缓冲区。这一步定义了文件中存储的路径结构和属性。

第3步:写入文件内容并关闭 Writer

使用 tw.Write 将文件的实际字节流写入缓冲区。所有文件写入完毕后,必须调用 tw.Close() 以写入必要的结束扇区/块,确保压缩包完整性。

第4步:将缓冲区内容持久化到磁盘

打开或创建目标文件(如 file.tar),使用 buf.WriteTo 或 ioutil.ReadAll 将缓冲区中的二进制数据写入磁盘文件。若需 .tar.gz 格式,可在 NewWriter 外层包裹 gzip.NewWriter。

package main

import (
	"archive/tar"
	"bytes"
	"log"
	"os"
)

func main() {
	// 1. 创建缓冲区
	var buf bytes.Buffer
	tw := tar.NewWriter(&buf)

	// 2. 定义要压缩的内容(模拟文件)
	var files = []struct {
		Name, Body string
	}{
		{"readme.txt", "This archive contains some text files."},
		{"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},
		{"todo.txt", "Get animal handling license."},
	}

	// 3. 循环写入每个文件
	for _, file := range files {
		hdr := &tar.Header{
			Name: file.Name,
			Mode: 0600,
			Size: int64(len(file.Body)),
		}
		// 写入文件头
		if err := tw.WriteHeader(hdr); err != nil {
			log.Fatal(err)
		}
		// 写入文件内容
		if _, err := tw.Write([]byte(file.Body)); err != nil {
			log.Fatal(err)
		}
	}

	// 4. 关闭 Writer,完成归档结构
	if err := tw.Close(); err != nil {
		log.Fatal(err)
	}

	// 5. 将缓冲区的压缩数据写入磁盘文件
	f, err := os.OpenFile("file.tar", os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	if _, err := buf.WriteTo(f); err != nil {
		log.Fatal(err)
	}
}

执行上述代码后,当前目录将生成 file.tar 文件。其结构与运行截图一致:

解压缩 Tar 文件

解压过程相对简单,核心是使用 tar.NewReader 读取文件流,并通过 Next() 方法遍历其中的文件条目。

第1步:打开源文件并创建 Reader

使用 os.Open 读取 .tar 文件。由于 os.File 实现了 io.Reader 接口,可直接传给 tar.NewReader 初始化一个读取对象。

第2步:遍历并提取文件

在循环中调用 tr.Next()。该方法返回下一个条目的 tar.Header。如果返回 io.EOF,表示归档结束。对于非 EOF 的其他错误,应终止程序或记录日志。

第3步:读取并保存内容

获取 Header 后,可以使用 io.Copy 将当前的 reader 位置(即文件内容)复制到 os.Stdout 或新的目标文件中。每次读取完一个文件后,下一次 Next() 会自动跳过该文件的填充字节,定位到下一个 Header。

package main

import (
	"archive/tar"
	"fmt"
	"io"
	"log"
	"os"
)

func main() {
	// 1. 打开要解压的文件
	file, err := os.Open("file.tar")
	if err != nil {
		log.Fatalln(err)
	}
	defer file.Close()

	// 2. 创建 Tar Reader
	tr := tar.NewReader(file)

	// 3. 遍历解压
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break // 到达文件末尾
		}
		if err != nil {
			log.Fatal(err)
		}

		// 打印文件名
		fmt.Printf("%s文件内容:\n", hdr.Name)

		// 4. 将内容输出到标准输出(或写入新文件)
		if _, err := io.Copy(os.Stdout, tr); err != nil {
			log.Fatal(err)
		}
		fmt.Println() // 换行
	}
}

运行解压程序后的输出效果如下:

以上就是Golang中使用archive/tar包进行文件压缩与解压的详细内容,更多关于Go语言tar.gz打包解包的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表