使用Go的compress/gzip压缩文件夹文件后解压异常求助
问题分析与解决方案:Go语言压缩多文件后解压异常
问题根源
gzip格式本身仅支持单个文件的压缩,你的代码将两个文件的内容直接依次写入同一个gzip Writer,并且每次覆盖gzipWriter.Name字段。解压工具最终只会识别最后一次设置的文件名,同时把两个文件的内容合并到该文件中,这就是你得到3MB的first.txt的原因。
解决方案
要实现多文件压缩并可完整恢复,需要先将文件打包为tar归档,再对tar包进行gzip压缩(即常见的.tar.gz/.tgz格式)——tar负责将多文件打包成单个归档,gzip负责压缩这个归档文件。
修改后的代码如下:
package services import ( "compress/gzip" "archive/tar" "fmt" "io" "os" "path/filepath" ) func compress() { currentDirectory, _ := os.Getwd() sourceFolder := currentDirectory + "/storages" outputFilename := currentDirectory + "/storages/output.tar.gz" // 创建输出文件 outputFile, err := os.Create(outputFilename) if err != nil { fmt.Println(err) return } defer outputFile.Close() // 创建gzip压缩写入器 gzipWriter, err := gzip.NewWriterLevel(outputFile, gzip.BestCompression) if err != nil { fmt.Println(err) return } defer gzipWriter.Close() // 创建tar归档写入器,包裹在gzip写入器外层 tarWriter := tar.NewWriter(gzipWriter) defer tarWriter.Close() err = filepath.Walk(sourceFolder, func(path string, info os.FileInfo, err error) error { if err != nil { fmt.Println(err) return err } // 跳过目录、gz文件和DS_Store if info.IsDir() || filepath.Ext(path) == ".gz" || filepath.Base(path) == ".DS_Store" { return nil } // 打开源文件 sourceFile, err := os.Open(path) if err != nil { fmt.Println(err) return err } defer sourceFile.Close() // 计算文件相对于源文件夹的路径,保留归档内的文件结构 relPath, err := filepath.Rel(sourceFolder, path) if err != nil { fmt.Println(err) return err } // 创建tar头部信息 header, err := tar.FileInfoHeader(info, "") if err != nil { fmt.Println(err) return err } // 修正头部的文件名(FileInfoHeader可能会丢失相对路径) header.Name = relPath // 写入tar头部 if err := tarWriter.WriteHeader(header); err != nil { fmt.Println(err) return err } // 写入文件内容到tar归档 _, err = io.Copy(tarWriter, sourceFile) if err != nil { fmt.Println(err) return err } fmt.Printf("已压缩 %s 到 %s\n", path, outputFilename) return nil }) if err != nil { fmt.Println(err) } } func main() { compress() }
关键说明
- 先通过
tar.NewWriter创建归档写入器,再用gzip.Writer包裹,实现"打包+压缩"的流程 - 使用
filepath.Rel获取文件相对于源文件夹的路径,确保解压后保留原始文件结构 - 每个文件对应一个独立的
tar.Header,保证解压时能识别为单独的文件
压缩完成后,你会得到output.tar.gz文件,用Keka解压即可恢复原始的两个文件。
内容的提问来源于stack exchange,提问作者lehoangnnx
相关产品推荐
相关产品推荐

