Introduction
Go, with its efficient standard library, makes zipping and unzipping files straightforward and efficient. Whether you're working with compressed archives for application packaging, data backup, or simply organizing and transferring files, knowing how to zip and unzip files within Go applications is invaluable.
Zipping Files and Folders
To zip files and folders in Go, we will use the 'archive/zip' package, which provides convenient functions to handle ZIP archives. Let's jump into the implementation.
Zipping a Single File
Below is a step-by-step guide to zipping a single file:
package main
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
)
func main() {
fileToZip := "example.txt"
zipFileName := "example.zip"
err := zipFiles(zipFileName, []string{fileToZip})
if err != nil {
log.Fatalf("Failed to zip file: %v", err)
}
fmt.Printf("Successfully zipped %s to %s\n", fileToZip, zipFileName)
}
func zipFiles(zipFileName string, files []string) error {
newZipFile, err := os.Create(zipFileName)
if err != nil {
return err
}
defer newZipFile.Close()
zipWriter := zip.NewWriter(newZipFile)
defer zipWriter.Close()
for _, file := range files {
if err := addFileToZip(zipWriter, file); err != nil {
return err
}
}
return nil
}
func addFileToZip(zipWriter *zip.Writer, fileName string) error {
fileToZip, err := os.Open(fileName)
if err != nil {
return err
}
defer fileToZip.Close()
info, err := fileToZip.Stat()
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = filepath.Base(fileName)
header.Method = zip.Deflate
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
_, err = io.Copy(writer, fileToZip)
return err
}
Zipping a Folder
To zip an entire folder, we'll recursively discover files, adding them to the zip. Here's how you can achieve that:
package main
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
)
func main() {
folderToZip := "folderName"
zipFileName := "folder.zip"
err := zipFolder(folderToZip, zipFileName)
if err != nil {
log.Fatalf("Failed to zip folder: %v", err)
}
fmt.Printf("Successfully zipped folder %s to %s\n", folderToZip, zipFileName)
}
func zipFolder(source, target string) error {
file, err := os.Create(target)
if err != nil {
return err
}
defer file.Close()
zipWriter := zip.NewWriter(file)
defer zipWriter.Close()
baseFolder := filepath.Base(source)
return filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == source {
return nil
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = filepath.Join(baseFolder, strings.TrimPrefix(path, source))
if info.IsDir() {
header.Name += "/"
_, err = zipWriter.CreateHeader(header)
return err
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
_, err = io.Copy(writer, file)
return err
})
}
Unzipping Files
To unzip files using Go, again, the 'archive/zip' package comes handy. Here's how you can extract files from a ZIP archive.
package main
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
)
func main() {
zipFileName := "example.zip"
outputDir := "extracted"
err := unzip(zipFileName, outputDir)
if err != nil {
log.Fatalf("Failed to unzip file: %v", err)
}
fmt.Printf("Successfully extracted %s to directory %s\n", zipFileName, outputDir)
}
func unzip(src string, dest string) error {
r, err := zip.OpenReader(src)
if err != nil {
return err
}
defer r.Close()
for _, f := range r.File {
fpath := filepath.Join(dest, f.Name)
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("illegal file path: %s", fpath)
}
if f.FileInfo().IsDir() {
os.MkdirAll(fpath, os.ModePerm)
continue
}
os.MkdirAll(filepath.Dir(fpath), os.ModePerm)
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return err
}
rc, err := f.Open()
if err != nil {
return err
}
_, err = io.Copy(outFile, rc)
outFile.Close()
rc.Close()
if err != nil {
return err
}
}
return nil
}
Conclusion
In this article, we've covered how to create ZIP archives and extract their contents using Go. Mastering these techniques allows for better file handling in your applications, promoting efficient storage and transfer solutions.