Golang compress/gzip文件压缩与解压实践
在Go语言的标准库中,compress/gzip包提供了对gzip格式文件的压缩与解压能力,无需引入第三方依赖即可快速实现相关功能。本文将介绍如何使用该包完成单文件压缩、解压以及多文件批量处理的常见场景。
单文件压缩实现
单文件压缩的核心流程是:先创建目标gzip文件,再初始化gzip写入器,最后将源文件内容拷贝到gzip写入器中。需要注意的是,操作完成后要及时关闭相关资源,避免数据丢失或文件句柄泄漏。
package main
import (
"compress/gzip"
"fmt"
"io"
"os"
)
// compressFile 压缩单个文件
// srcPath 源文件路径,dstPath 目标gzip文件路径
func compressFile(srcPath, dstPath string) error {
// 打开源文件
srcFile, err := os.Open(srcPath)
if err != nil {
return fmt.Errorf("打开源文件失败: %v", err)
}
defer srcFile.Close()
// 创建目标gzip文件
dstFile, err := os.Create(dstPath)
if err != nil {
return fmt.Errorf("创建目标文件失败: %v", err)
}
defer dstFile.Close()
// 初始化gzip写入器,默认压缩级别为6
gzipWriter, err := gzip.NewWriterLevel(dstFile, gzip.DefaultCompression)
if err != nil {
return fmt.Errorf("初始化gzip写入器失败: %v", err)
}
defer gzipWriter.Close()
// 将源文件内容拷贝到gzip写入器
_, err = io.Copy(gzipWriter, srcFile)
if err != nil {
return fmt.Errorf("拷贝文件内容失败: %v", err)
}
// 刷新写入器确保数据全部写入
return gzipWriter.Flush()
}
func main() {
src := "test.txt"
dst := "test.txt.gz"
if err := compressFile(src, dst); err != nil {
fmt.Printf("压缩失败: %v\n", err)
return
}
fmt.Println("单文件压缩完成")
}上述代码中,gzip.NewWriterLevel方法支持自定义压缩级别,参数范围是1到9,数值越大压缩率越高但速度越慢,默认使用6级即可满足大部分场景需求。另外,必须调用gzipWriter.Close方法,它会自动写入gzip文件的尾部信息,保证压缩文件格式正确。
单文件解压实现
解压流程与压缩相反:先打开gzip压缩文件,初始化gzip读取器,再将读取器中的内容拷贝到目标文件中即可。
package main
import (
"compress/gzip"
"fmt"
"io"
"os"
)
// decompressFile 解压单个gzip文件
// srcPath 源gzip文件路径,dstPath 目标解压后文件路径
func decompressFile(srcPath, dstPath string) error {
// 打开源gzip文件
srcFile, err := os.Open(srcPath)
if err != nil {
return fmt.Errorf("打开源gzip文件失败: %v", err)
}
defer srcFile.Close()
// 初始化gzip读取器
gzipReader, err := gzip.NewReader(srcFile)
if err != nil {
return fmt.Errorf("初始化gzip读取器失败: %v", err)
}
defer gzipReader.Close()
// 创建目标文件
dstFile, err := os.Create(dstPath)
if err != nil {
return fmt.Errorf("创建目标文件失败: %v", err)
}
defer dstFile.Close()
// 将gzip读取器内容拷贝到目标文件
_, err = io.Copy(dstFile, gzipReader)
return err
}
func main() {
src := "test.txt.gz"
dst := "test_decompressed.txt"
if err := decompressFile(src, dst); err != nil {
fmt.Printf("解压失败: %v\n", err)
return
}
fmt.Println("单文件解压完成")
}如果gzip文件本身损坏或者不是合法的gzip格式,gzip.NewReader会返回错误,实际使用时可以根据错误类型做更细粒度的处理。
批量文件压缩与解压
实际业务中经常需要处理多个文件的压缩解压,我们可以通过遍历文件列表批量执行操作。以下示例实现了指定目录下所有txt文件的批量压缩,以及对应gzip文件的批量解压。
package main
import (
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// batchCompress 批量压缩指定目录下的txt文件
// dirPath 目标目录,输出文件后缀为.gz
func batchCompress(dirPath string) error {
files, err := os.ReadDir(dirPath)
if err != nil {
return fmt.Errorf("读取目录失败: %v", err)
}
for _, file := range files {
if file.IsDir() {
continue
}
// 只处理txt文件
if !strings.HasSuffix(file.Name(), ".txt") {
continue
}
srcPath := filepath.Join(dirPath, file.Name())
dstPath := srcPath + ".gz"
srcFile, err := os.Open(srcPath)
if err != nil {
fmt.Printf("跳过文件 %s: 打开失败 %v\n", srcPath, err)
continue
}
dstFile, err := os.Create(dstPath)
if err != nil {
srcFile.Close()
fmt.Printf("跳过文件 %s: 创建目标文件失败 %v\n", srcPath, err)
continue
}
gzipWriter, err := gzip.NewWriterLevel(dstFile, gzip.DefaultCompression)
if err != nil {
srcFile.Close()
dstFile.Close()
fmt.Printf("跳过文件 %s: 初始化gzip写入器失败 %v\n", srcPath, err)
continue
}
_, err = io.Copy(gzipWriter, srcFile)
srcFile.Close()
gzipWriter.Close()
dstFile.Close()
if err != nil {
fmt.Printf("压缩文件 %s 失败: %v\n", srcPath, err)
} else {
fmt.Printf("压缩文件 %s 完成\n", srcPath)
}
}
return nil
}
// batchDecompress 批量解压指定目录下的gz文件
// dirPath 目标目录
func batchDecompress(dirPath string) error {
files, err := os.ReadDir(dirPath)
if err != nil {
return fmt.Errorf("读取目录失败: %v", err)
}
for _, file := range files {
if file.IsDir() {
continue
}
if !strings.HasSuffix(file.Name(), ".gz") {
continue
}
srcPath := filepath.Join(dirPath, file.Name())
// 解压后文件名去掉.gz后缀
dstPath := strings.TrimSuffix(srcPath, ".gz")
srcFile, err := os.Open(srcPath)
if err != nil {
fmt.Printf("跳过文件 %s: 打开失败 %v\n", srcPath, err)
continue
}
gzipReader, err := gzip.NewReader(srcFile)
if err != nil {
srcFile.Close()
fmt.Printf("跳过文件 %s: 初始化gzip读取器失败 %v\n", srcPath, err)
continue
}
dstFile, err := os.Create(dstPath)
if err != nil {
srcFile.Close()
gzipReader.Close()
fmt.Printf("跳过文件 %s: 创建目标文件失败 %v\n", srcPath, err)
continue
}
_, err = io.Copy(dstFile, gzipReader)
srcFile.Close()
gzipReader.Close()
dstFile.Close()
if err != nil {
fmt.Printf("解压文件 %s 失败: %v\n", srcPath, err)
} else {
fmt.Printf("解压文件 %s 完成\n", srcPath)
}
}
return nil
}
func main() {
targetDir := "./test_files"
fmt.Println("开始批量压缩...")
if err := batchCompress(targetDir); err != nil {
fmt.Printf("批量压缩出错: %v\n", err)
}
fmt.Println("\n开始批量解压...")
if err := batchDecompress(targetDir); err != nil {
fmt.Printf("批量解压出错: %v\n", err)
}
}批量处理时建议对每个文件的操作做错误兜底,避免单个文件处理失败导致整个流程中断。如果需要处理嵌套目录,可以结合filepath.Walk方法递归遍历所有子目录下的文件。
注意事项
- gzip格式仅支持单文件压缩,如果需要压缩多个文件或整个目录,通常需要先打包成tar格式,再用gzip压缩,即常见的.tar.gz格式,此时可以结合
archive/tar包一起使用。 - 压缩大文件时,
io.Copy会按块读写,不会一次性加载整个文件到内存,内存占用可控,适合处理大文件场景。 - 所有文件资源操作都要使用
defer或者手动关闭,避免文件句柄泄漏,尤其是批量处理场景中,未关闭的文件句柄可能快速耗尽系统资源。
Go语言gzip压缩文件解压compress/gzip批量处理 本作品最后修改时间:2026-05-23 11:37:05