golang 压缩文件和解压文件

以下代码只是压缩单个文件,如果是目录可以先用archive/tar 包归档目录,然后压缩归档后的问天。

package main

import (
	"compress/gzip"
	"encoding/base64"
	"fmt"
	"io"
	"os"
	"path/filepath"
)

// 压缩文件,支持中文名
func CompressFile(src, dst string) error {
	inFile, err := os.Open(src)
	if err != nil {
		return err
	}
	defer inFile.Close()

	outFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer outFile.Close()

	gw := gzip.NewWriter(outFile)
	defer gw.Close()

	// 将中文文件名转成 base64,放在 Comment 字段
	baseName := filepath.Base(src)
	encodedName := base64.StdEncoding.EncodeToString([]byte(baseName))
	gw.Comment = "B64FN:" + encodedName

	// Header.Name 只能放 ASCII,用占位符
	gw.Name = "file"

	_, err = io.Copy(gw, inFile)
	return err
}

// 解压文件,恢复中文名
func DecompressFile(src, dstDir string) (string, error) {
	inFile, err := os.Open(src)
	if err != nil {
		return "", err
	}
	defer inFile.Close()

	gr, err := gzip.NewReader(inFile)
	if err != nil {
		return "", err
	}
	defer gr.Close()

	// 默认文件名
	outName := gr.Name
	if outName == "" {
		outName = "file"
	}

	// 如果 Comment 有 base64 名字,就还原
	if len(gr.Comment) > 5 && gr.Comment[:6] == "B64FN:" {
		decoded, err := base64.StdEncoding.DecodeString(gr.Comment[6:])
		if err == nil {
			outName = string(decoded)
		}
	}

	outPath := filepath.Join(dstDir, outName)
	outFile, err := os.Create(outPath)
	if err != nil {
		return "", err
	}
	defer outFile.Close()

	_, err = io.Copy(outFile, gr)
	return outPath, err
}

func main() {
	src := "测试文件.txt"
	dst := "test.gz"

	// 压缩
	if err := CompressFile(src, dst); err != nil {
		fmt.Println("压缩失败:", err)
		return
	}
	fmt.Println("压缩成功:", dst)

	// 解压
	out, err := DecompressFile(dst, ".")
	if err != nil {
		fmt.Println("解压失败:", err)
		return
	}
	fmt.Println("解压成功:", out)
}

posted @ 2025-08-21 16:17  熊先生不开玩笑  阅读(12)  评论(0)    收藏  举报