How to uncompress a file in Golang
To protect and secure files, files are zipped and compressed.
However, there is a need to unzip files for their usage.
The .ZIP extension is the standard file extension for compressed files. However, there are other file extensions used for zipped files which include the following formats:
.JAR.WAR.DOCX.ODS.ODP
Go’s standard library has a package called "archive/zip". This package is used for compressing and decompressing files.
Packages in Go
Before delving into unzipping a file, there are core components that help us achieve this. Go’s standard library provides all the packages needed without the need to import an external library. We will be using five packages to achieve this. The packages are:
- The
ospackage - The
iopackage - The
archive/zippackage - The
path/filepathpackage - The
fmtpackage
The zip.OpenReader function
To unzip a file, the first thing to be done is to open the file. The zip.OpenReader handles this for us. So how does this function work?
The OpenReader function takes care of opening the zip file specified by it’s name and returns *ReadCloser and an error.
// The zip.OpenReader functionfunc OpenReader(name string) (*ReadCloser, error)//The zip.Reader typetype Reader struct{File []*FileComment string}
The reader
-
After the zip file is opened, it returns
*ReadCloserwhich is an instance ofzip.Reader.zip.Readeris a struct that has the fieldFileof type[]*zip.Fileand fieldCommentof typestring. -
A head start in the unzipping process is to name the destination folder to save the file to be unzipped. The file
destinationFolderis declared as"unzipFolder".
package mainimport ("fmt""archive/zip""io""os""path/filepath")func main() {fileDestinationFolder := "unzipFolder"//The first thing is to open the zipped file.openedFile, err := zip.OpenReader("unzip/archive.zip")if err != nil{panic(err)}// postpone the closing of the file.defer openedFile.Close()}
- The zipped file is opened with the
zip.OpenReaderfunction which takes in a parameter of the link to the folder where the zipped file folder is located. This returns anerrorand the instance ofzip.Reader. In the code above, it is namedopenedFile. This is a slice of typeFile.
package mainimport ("fmt""archive/zip""io""os""path/filepath")func main() {for _, file := range openedFile.File{filePath := filepath.Join(destinationFolder,file.Name)fmt.Println("unzipping file", filePath)// if the file is an empty directory, create a directoryif file.FileInfo().IsDir(){// create the directoryos.MkdirAll(filePath,os.ModePerm)continue}}
-
The
openFile, which is a slice of typeFile, is looped through using therangemethod to get an individual file. -
Using the
filepath.Join()method, thedestinationfolderand thefile.Nameare joined into a single path namedfilePath. This is where the unzipping process starts. -
After this is done, the next step is to create a directory. This is achieved using the
os.MkdirAll()method, if the file is in an empty directory.
if err := os.MkdirAll(filepath.Dir(filePath),os.ModePerm); err != nil{panic(err)}else {destinationFile, err := os.OpenFile(filePath,os.O_CREATE|os.O_WRONLY|os.O_TRUNC,file.Mode())if err != nil{panic(err)}//Opening the file and copy it's contentsfileInArchive, err := file.Open()if err != nil{}if _, err := io.Copy(destinationFile,fileInArchive); err != nil{panic(err)}destinationFile.Close()fileInArchive.Close()}}}
-
The next condition checks if the file is within a directory. If these two conditions fail, then it opens the
filePathusing theos.Openfile()method. -
The
os.O_CREATEcreates a file if the file does not exist in the destination folder. -
The
os.O_WRONLYopens the file in a write-only mode andos.O_TRUNCtruncates the file when opened. Any of these could happen since it is executed by anORoperator. -
This operation returns an
errorand thedestinationFileof type*file. Theerroris handled. -
The final step is to open the contents of the file saved as
fileInAchived. This is copied into thedestinationFileusing theiopackage.
GOROOT=/usr/local/go #gosetupGOPATH=/Users/decagon/go #gosetup/usr/local/go/bin/go build -o /private/var/folders/8w/g4zndjnj2yl3p12p3ht_hryc0000gn/T/GoLand/___go_build_espresso_unzip espresso/unzip #gosetup/private/var/folders/8w/g4zndjnj2yl3p12p3ht_hryc0000gn/T/GoLand/___go_build_espresso_unzipopen zip archiveunzipping file unzipFolder/csv/test.csvProcess finished with the exit code 0
Conclusion
Uncompressing the "unzip/archive.zip" file requires us to create a destinationFolder. The zipped file was opened with the openReader function. The openReader function returns an instance of zip.Reader and an error. The zip.Reader is a struct that contains a field File of type []*zip.File and a Comment of type String.
The derived file is a slice. To get the individual file, we had to loop it and join the file name with the destinationFolder. We checked if the file was within an empty directory. A directory was created if it failed the conditions. The filePath was opened using the os.Openfile() method. The final step was to open the contents of the file saved as fileInAchived before copying it into thedestinationFile using the io.Copymethod.
Free Resources