golang壓縮與解壓縮文件的示例代碼
壓縮
入口壓縮函數(shù)
useBasePathInZip參數(shù):
為 false 相當(dāng)于全文件視圖,zip中沒有目錄
為 true表示保留源文件的路徑(srcPaths如果是相對路徑,則壓縮后zip文件中也是相對路徑)
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è)對象.\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對象
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平臺
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平臺
_, 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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文搞懂如何實(shí)現(xiàn)Go 超時(shí)控制
這篇文章主要介紹了一文搞懂如何實(shí)現(xiàn)Go 超時(shí)控制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Apache?IoTDB開發(fā)系統(tǒng)之Go原生接口方法
這篇文章主要為大家介紹了?Apache?IoTDB開發(fā)系統(tǒng)之Go原生接口方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
Go語言對JSON數(shù)據(jù)進(jìn)行序列化和反序列化
這篇文章介紹了Go語言對JSON數(shù)據(jù)進(jìn)行序列化和反序列化的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07

