解压代码
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
}
标签:解压,return,nil,err,golang,file,os,压缩包,string
From: https://www.cnblogs.com/xingzr/p/18188626