golang壓縮與解壓縮文件的示例代碼
壓縮
入口壓縮函數(shù)
useBasePathInZip參數(shù):
為 false 相當(dāng)于全文件視圖,zip中沒有目錄
為 true表示保留源文件的路徑(srcPaths如果是相對(duì)路徑,則壓縮后zip文件中也是相對(duì)路徑)
func compress(srcPaths []string, outputPath string, useBasePathInZip bool) { if len(srcPaths) == 0 { return } file, openErr := os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if openErr != nil { fmt.Printf("failed to open file %s: %v\n", outputPath, openErr) return } defer file.Close() zipWriter := zip.NewWriter(file) defer zipWriter.Close() for _, path := range srcPaths { info, err := os.Stat(path) if err != nil { fmt.Printf("failed to stat file %s: %v\n", path, err) return } if info.IsDir() { fmt.Printf("%s is dir...\n", path) err = addFilesToDirectory(zipWriter, path, "", useBasePathInZip) if err != nil { return } continue } fmt.Printf("%s is file...\n", path) if err = compressFile(zipWriter, path, useBasePathInZip); err != nil { log.Fatalf("add file %s to zip failed: %s", path, err) } } }
核心處理
遞歸壓縮目錄中的所有文件
func addFilesToDirectory(zw *zip.Writer, newDir, baseInZip string, useBasePathInZip bool) error { files, err := ioutil.ReadDir(newDir) if err != nil { return err } fmt.Printf("目錄 %s 下包含 %d 個(gè)對(duì)象.\n", newDir, len(files)) var newBaseInZip string for _, fileInfo := range files { if useBasePathInZip { newBaseInZip = filepath.Join(baseInZip, fileInfo.Name()) } newFullPath := filepath.Join(newDir, fileInfo.Name()) fmt.Printf("\tcheck filename=%s, newFullPath=%s, newBaseInZip=%s \n", fileInfo.Name(), newFullPath, newBaseInZip) // 是目錄,遞歸處理 if fileInfo.IsDir() { if err = addFilesToDirectory(zw, newFullPath, newBaseInZip, useBasePathInZip); err != nil { return err } continue } // 處理單個(gè)文件 if err = compressFile(zw, newFullPath, useBasePathInZip); err != nil { return err } } return nil }
壓縮單個(gè)文件
func compressFile(zw *zip.Writer, srcFile string, useBasePathInZip bool) error { fileToZip, err := os.Open(srcFile) if err != nil { log.Fatalf("compressFile failed to open %s: %v", srcFile, err) return err } defer fileToZip.Close() var zipFile io.Writer if !useBasePathInZip { // 獲得源文件FileInfo對(duì)象 info, err := fileToZip.Stat() if err != nil { fmt.Printf("failed to open file %s: %v\n", srcFile, err) return err } // 創(chuàng)建新的ZIP文件頭,并設(shè)置其內(nèi)部路徑僅為文件名 header, err := zip.FileInfoHeader(info) if err != nil { fmt.Printf("failed to create file header for %s: %v\n", srcFile, err) return err } fmt.Println("名稱=", header.Name) // 設(shè)置壓縮后的文件名為源文件名(去掉路徑) header.Name = filepath.Base(srcFile) // 基于主zw流創(chuàng)建該文件的目標(biāo)zip平臺(tái) zipFile, err = zw.CreateHeader(header) if err != nil { return err } } else { zipFile, err = zw.Create(srcFile) if err != nil { return err } } // 將源文件Copy到目標(biāo)zip平臺(tái) _, err = io.Copy(zipFile, fileToZip) fmt.Printf("壓縮 %s 完成 %v\n", srcFile, err) return err }
調(diào)用壓縮
func main() { var srcPaths = []string{"fzip/zipt/a.txt", "fzip/unzip.go"} compress(srcPaths, "./a.zip", true) }
解壓縮
func unzip(unzipFile, unzipDir string) { zipReader, _ := zip.OpenReader(unzipFile) for i, file := range zipReader.Reader.File { fmt.Printf("正在壓縮第 %d 個(gè). name=%s Comment=%s, isDir=%v, size=%d.\n", i+1, file.Name, file.Comment, file.FileInfo().IsDir(), file.FileInfo().Size()) func(i int, file *zip.File) { zippedFile, err := file.Open() if err != nil { log.Fatal(err) } defer zippedFile.Close() extractedFilePath := filepath.Join(unzipDir, file.Name) if file.FileInfo().IsDir() { _ = os.MkdirAll(extractedFilePath, file.Mode()) // 權(quán)限不變 fmt.Println("dir Created:", extractedFilePath) return } fmt.Println("file extracted: ", file.Name) func() { outputFile, err := os.OpenFile(extractedFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode()) if err != nil { log.Fatal(err) } defer outputFile.Close() _, err = io.Copy(outputFile, zippedFile) if err != nil { log.Fatal(err) } }() }(i, file) } }
到此這篇關(guān)于golang壓縮與解壓縮文件的示例代碼的文章就介紹到這了,更多相關(guān)golang壓縮與解壓縮文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go?for-range?的?value值地址每次都一樣的原因解析
循環(huán)語(yǔ)句是一種常用的控制結(jié)構(gòu),在?Go?語(yǔ)言中,除了?for?關(guān)鍵字以外,還有一個(gè)?range?關(guān)鍵字,可以使用?for-range?循環(huán)迭代數(shù)組、切片、字符串、map?和?channel?這些數(shù)據(jù)類型,這篇文章主要介紹了Go?for-range?的?value值地址每次都一樣的原因解析,需要的朋友可以參考下2023-05-05go語(yǔ)言題解LeetCode228匯總區(qū)間示例詳解
這篇文章主要為大家介紹了go語(yǔ)言題解LeetCode228匯總區(qū)間示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Golang 定時(shí)器(Timer 和 Ticker),這篇文章就夠了
這篇文章主要介紹了Golang 定時(shí)器(Timer 和 Ticker),這篇文章就夠了,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10Golang實(shí)現(xiàn)對(duì)map的并發(fā)讀寫的方法示例
這篇文章主要介紹了Golang實(shí)現(xiàn)對(duì)map的并發(fā)讀寫的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2019-03-03Go語(yǔ)言基礎(chǔ)單元測(cè)試與性能測(cè)試示例詳解
這篇文章主要為大家介紹了Go語(yǔ)言基礎(chǔ)單元測(cè)試與性能測(cè)試示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助祝大家多多進(jìn)步2021-11-11Golang實(shí)現(xiàn)KV存儲(chǔ)引擎實(shí)例探究
這篇文章主要為大家介紹了Golang實(shí)現(xiàn)KV存儲(chǔ)引擎實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01