在Go (Golang) 中处理ZIP压缩包
在现代Go开发中,经常需要处理压缩包——用于打包日志、分发配置、备份或在微服务之间传输数据。Go标准库提供了强大且灵活的archive/zip包,无需第三方依赖即可创建、读取和修改ZIP压缩包。本文将详细讲解在Go中处理ZIP压缩包的所有方面。
archive/zip包概述
archive/zip包是Go标准库的一部分,支持:
- 读取和写入ZIP压缩包(PKWARE格式)
- 使用Deflate和Stored(无压缩)方法进行压缩
- 处理压缩包内的文件和目录
- 支持压缩包和单个文件的注释
- 设置文件属性(日期、权限)
- 流式处理(压缩包大小可达数GB)
主要类型:用于创建压缩包的zip.Writer和用于读取的zip.Reader。
创建ZIP压缩包
创建压缩包使用zip.NewWriter,它接受一个io.Writer。每个文件通过Create或CreateHeader添加。
package main
import ( "archive/zip" "bytes" "fmt" "io" "log" "os")
func main() { // 创建压缩包缓冲区 buf := new(bytes.Buffer) writer := zip.NewWriter(buf)
// 添加文本文件 file1, err := writer.Create("hello.txt") if err != nil { log.Fatal(err) } _, err = file1.Write([]byte("Hello, Go ZIP!")) if err != nil { log.Fatal(err) }
// 添加带子目录的文件 file2, err := writer.Create("config/settings.json") if err != nil { log.Fatal(err) } _, err = file2.Write([]byte(`{"version": 1, "debug": true}`)) if err != nil { log.Fatal(err) }
// 必须关闭writer err = writer.Close() if err != nil { log.Fatal(err) }
// 将压缩包保存到磁盘 err = os.WriteFile("example.zip", buf.Bytes(), 0644) if err != nil { log.Fatal(err) } fmt.Println("压缩包已创建: example.zip")}读取和提取压缩包中的文件
读取压缩包使用zip.NewReader,需要传入io.ReaderAt和压缩包大小。可以读取到内存中,也可以流式处理。
func readArchive() { // 打开压缩包文件 reader, err := zip.OpenReader("example.zip") if err != nil { log.Fatal(err) } defer reader.Close()
// 遍历压缩包中的所有文件 for _, file := range reader.File { fmt.Printf("文件: %s (大小: %d 字节)", file.Name, file.UncompressedSize64)
// 打开压缩包内的文件 rc, err := file.Open() if err != nil { log.Fatal(err) }
// 读取内容 content, err := io.ReadAll(rc) if err != nil { log.Fatal(err) } rc.Close()
fmt.Printf("内容: %s
", content) }}添加带元数据的文件
使用zip.FileHeader可以设置日期、权限和压缩方法:
func addFileWithMetadata(w *zip.Writer, name, content string) error { header := &zip.FileHeader{ Name: name, Method: zip.Deflate, // 使用Deflate(压缩) } // 设置修改时间 header.SetModTime(time.Now()) // 设置权限(Unix rw-r--r--) header.SetMode(0644)
f, err := w.CreateHeader(header) if err != nil { return err } _, err = f.Write([]byte(content)) return