golang zip压缩/解压缩用法
最近有個需求,需要寫個腳本,但要編譯為exe可執行文件,首先考慮python打包,奈何使用pyinstaller打包后,出現各種各樣的運行錯誤,最后放棄了,改為golang重寫。因為要用到創建和解壓zip文件,golang中使用zip模塊的功能,遠沒有python那么方便。
一、壓縮部分
把文件或者文件夾壓縮為zip文件,主要過程就是創建目的zip文件,然后遍歷源目錄,將源目錄下的文件拷貝到目的zip文件中,最重要的2個方法:
1、zip.newWriter? 創建一個向zip文件中寫入的writer
2、writer.CreateHeader 向zip文件頭中寫入內容
其過程網上一搜一大把,雷同的很多,果然大家都是代碼的搬運工。在網上看到用的最多的一例,見原文連接:https://blog.csdn.net/lengyuezuixue/article/details/79651549,
import ("archive/zip""fmt""io""os""strings" )//壓縮文件 //files 文件數組,可以是不同dir下的文件或者文件夾 //dest 壓縮文件存放地址 func Compress(files []*os.File, dest string) error {d, _ := os.Create(dest)defer d.Close()w := zip.NewWriter(d)defer w.Close()for _, file := range files {err := compress(file, "", w)if err != nil {return err}}return nil }func compress(file *os.File, prefix string, zw *zip.Writer) error {info, err := file.Stat()if err != nil {return err}if info.IsDir() {prefix = prefix + "/" + info.Name()fileInfos, err := file.Readdir(-1)if err != nil {return err}for _, fi := range fileInfos {f, err := os.Open(file.Name() + "/" + fi.Name())if err != nil {return err}err = compress(f, prefix, zw)if err != nil {return err}}} else {header, err := zip.FileInfoHeader(info)header.Name = prefix + "/" + header.Nameif err != nil {return err}writer, err := zw.CreateHeader(header)if err != nil {return err}_, err = io.Copy(writer, file)file.Close()if err != nil {return err}}return nil }以上代碼Compress方法在大多數情況下沒有問題,但有一個缺陷,不能壓縮空目錄,源目錄中含有空目錄及嵌套的空目錄,都不能被壓縮。仔細讀一遍代碼可知,以上代碼是通過遞歸遍歷源目錄中的文件,然后將文件copy到目的zip中,第57行。但沒有考慮到空目錄的情況,從第31行,IsDir后,對空目錄沒有做任何處理導致空目錄被跳過。實例運行如圖:
可以看到對空目錄,以上代碼沒有進行處理。像將其優化,增加對非空目錄的處理,完整如下:
import ("archive/zip""fmt""io""os""strings" )//壓縮文件 //src 可以是不同dir下的文件或者文件夾 //dest 壓縮文件存放地址 func Compress(src string, dest string) error {f, err := os.Open(src)if err != nil {return err}files := []*os.File{f}d, _ := os.Create(dest)defer d.Close()w := zip.NewWriter(d)defer w.Close()for _, file := range files {err := compress(file, "", w)if err != nil {return err}}return nil }func compress(file *os.File, prefix string, zw *zip.Writer) error {info, err := file.Stat()if err != nil {return err}if info.IsDir() {prefix = prefix + "/" + info.Name()fileInfos, err := file.Readdir(-1)if err != nil {return err}// 增加對空目錄的判斷if len(fileInfos) <= 0 {header, err := zip.FileInfoHeader(info)header.Name = prefixif err != nil {fmt.Println("error is:"+err.Error())return err}_, err = zw.CreateHeader(header)if err != nil {fmt.Println("create error is:"+err.Error())return err}file.Close()}for _, fi := range fileInfos {f, err := os.Open(file.Name() + "/" + fi.Name())if err != nil {return err}err = compress(f, prefix, zw)if err != nil {return err}}} else {header, err := zip.FileInfoHeader(info)header.Name = prefix + "/" + header.Nameif err != nil {return err}writer, err := zw.CreateHeader(header)if err != nil {return err}_, err = io.Copy(writer, file)file.Close()if err != nil {return err}}return nil }//解壓 func DeCompress(zipFile, dest string) error {reader, err := zip.OpenReader(zipFile)if err != nil {return err}defer reader.Close()for _, file := range reader.File {rc, err := file.Open()if err != nil {return err}defer rc.Close()filename := dest + file.Nameerr = os.MkdirAll(getDir(filename), 0755)if err != nil {return err}w, err := os.Create(filename)if err != nil {return err}defer w.Close()_, err = io.Copy(w, rc)if err != nil {return err}w.Close()rc.Close()}return nil }func getDir(path string) string {return subString(path, 0, strings.LastIndex(path, "/")) }func subString(str string, start, end int) string {rs := []rune(str)length := len(rs)if start < 0 || start > length {panic("start is wrong")}if end < start || end > length {panic("end is wrong")}return string(rs[start:end]) }在43行-56行增加了對空目錄的處理,直接將目錄名寫入到zip header中。可以完美解決空目錄不處理的問題。
總結
以上是生活随笔為你收集整理的golang zip压缩/解压缩用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java-php-python-ssm校
- 下一篇: 史上最全的CTF保姆教程 从入门到入狱【