golang 压缩包解压问题汇总

解压代码

package main

import (
	"archive/zip"
	"bytes"
	"fmt"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
)

func main() {
	fileInfo, err := Unzip("./test.zip", "./test")

	fmt.Println(err)
	fmt.Println(fileInfo)

}

func Unzip(zipFile string, destDir string) ([]string, error) {
	// 获取压缩包信息
	zipReader, err := zip.OpenReader(zipFile)
	if err != nil {
		return []string{}, err
	}
	defer zipReader.Close()
	// 解压目录是否存在,不存在则创建
	if _, err = os.Stat(destDir); os.IsNotExist(err) {
		err = os.MkdirAll(destDir, os.ModePerm)
		if err != nil {
			return []string{}, err
		}
	}
	// 解压后全部文件路径
	var filePathSlice []string
	for _, file := range zipReader.File { // 循环获取压缩包里的文件信息
		path, err := func() (string, error) {
			var decodeName string
			if file.Flags == 0 { //如果标致位是0  则是默认的本地编码   默认为gbk
				i := bytes.NewReader([]byte(file.Name))
				decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder())
				content, _ := ioutil.ReadAll(decoder)
				decodeName = string(content)
			} else {
				decodeName = file.Name
			}
			path := filepath.Join(destDir, decodeName)
			// 如果是目录,就创建目录
			if file.FileInfo().IsDir() {
				if err = os.MkdirAll(path, file.Mode()); err != nil {
					return "", err
				}
				return path, nil
			}
			if err = os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
				return "", err
			}
			// 获取到 Reader
			fr, err := file.Open()
			if err != nil {
				return "", err
			}
			defer fr.Close()
			// 创建要写出的文件对应的 Write
			fw, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, file.Mode())
			if err != nil {
				return "", err
			}
			defer fw.Close()
			_, err = io.Copy(fw, fr)
			if err != nil {
				return "", err
			}
			return path, nil
		}()
		if err != nil {
			return []string{}, err
		} else {
			filePathSlice = append(filePathSlice, path)
		}
	}
	return filePathSlice, nil
}

注意问题

中文文件名解压乱码

原因:winrar压缩时,默认采用本地编码方式来进行压缩。在中国,本地编码方式一般是GBK。而我们知道go语言字符串都是utf-8格式的,所以有可能出现乱码的情况

解决方案:判定文件名编码方式,如果为GBK,则转换GBK=》utf-8

对应代码:

if file.Flags == 0 { //如果标致位是0  则是默认的本地编码   默认为gbk
	i := bytes.NewReader([]byte(file.Name))
	decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder())
	content, _ := ioutil.ReadAll(decoder)
	decodeName = string(content)
} else {
	decodeName = file.Name
}

参考文章:https://www.php.cn/faq/438093.html

获取压缩文件信息时,不能获取到目录信息

原因:Windows的压缩功能(如“发送到”>“压缩(zipped)文件夹”)在处理只有一个文件的文件夹时,可能会简化压缩过程,以提高效率和节省存储空间。在这种情况下,它不会记录空的外层文件夹,而是直接将文件作为压缩包内的顶级元素。这是因为它认为保留一个只包含一个文件的空文件夹结构没有必要,这样做可以减少压缩文件的大小和解压后的复杂性。

解决方案:获取文件信息后,多做一步确保文件夹存在

对应代码:

if err = os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
	return "", err
}
posted @   元気田支店长  阅读(86)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示