How to Uncompress a File in Golang?
Last Updated :
28 Jul, 2020
As per Wikipedia, data compression or file compression can be understood as a process of reducing the size of a particular file/folder/whatever data while still preserving the original data. Lesser file size has a lot of benefits as it will then occupy lesser storage area giving you more space for other data to occupy, transfer the file faster as the size is lesser and various other perks unlock upon file compression. The compressed files are stored in the form of compressed file extension folders such as ".zip",".rar",".tar.gz", ".arj" and ".tgz". Compression reduces the file size to maximum compression size. If it cannot be compressed further then the size shall remain the same and not lesser.
After data is compressed we often feel the need to undo them in order to make them readily accessible. This undoing process is called uncompression. The process of extracting a normal file/folder from a compressed file is termed as uncompression.
But How to Uncompress the File?
There are various software that performs such tasks for us; one best example I know is WinRAR/WinZip. They are capable of compressing and uncompressing data files. But how long do we depend on software alone? Most of their features come paid and apart from the financial aspect, do we coders have to eternally depend on outsourced applications to fulfill our needs? Or can we dig out our own ways to meet our requirements? Well, data uncompression can also be done manually. One such manual method is discussed below using GoLang.
Example:
Case scenario: Files present inside a folder that's archived. The program extracts all files to the target destination.
Go
package main
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
)
func main() {
// Unzip accepts two arguments:
// First argument represents
// the source directory
// path where archived files are present.
// Second argument represents the
// destination directory path where unzipped
// files will be stored after uncompression.
// Note that destination folder will be created
// inside pwd and then files will be
// extracted into the destination folder.
// Unzip returns 2 values:
// names of files in archived directory & error (if any)
files, err := Unzip("compression-test.zip", "uncompressed files")
// If any error is present then that
// error value will be assigned to err
// In case of no error, err will be equal to nill
// condition check to ensure if any error
// is present we'd print the error message
// and log the error using log.Fatal
if err != nil {
log.Fatal(err)
}
fmt.Println("Unzipped the following files:\n" + strings.Join(files, "\n"))
//end of main function
}
// Unzip will decompress a zip archived file,
// copying all files and folders
// within the zip file (parameter 1)
// to an output directory (parameter 2).
func Unzip(src string, destination string) ([]string, error) {
// a variable that will store any
//file names available in a array of strings
var filenames []string
// OpenReader will open the Zip file
// specified by name and return a ReadCloser
// Readcloser closes the Zip file,
// rendering it unusable for I/O
// It returns two values:
// 1. a pointer value to ReadCloser
// 2. an error message (if any)
r, err := zip.OpenReader(src)
// if there is any error then
// (err!=nill) becomes true
if err != nil {
// and this block will break the loop
// and return filenames gathered so far
// with an err message, and move
// back to the main function
return filenames, err
}
defer r.Close()
// defer makes sure the file is closed
// at the end of the program no matter what.
for _, f := range r.File {
// this loop will run until there are
// files in the source directory & will
// keep storing the filenames and then
// extracts into destination folder until an err arises
// Store "path/filename" for returning and using later on
fpath := filepath.Join(destination, f.Name)
// Checking for any invalid file paths
if !strings.HasPrefix(fpath, filepath.Clean(destination)+string(os.PathSeparator)){
return filenames, fmt.Errorf("%s is an illegal filepath", fpath)
}
// the filename that is accessed is now appended
// into the filenames string array with its path
filenames = append(filenames, fpath)
if f.FileInfo().IsDir() {
// Creating a new Folder
os.MkdirAll(fpath, os.ModePerm)
continue
}
// Creating the files in the target directory
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return filenames, err
}
// The created file will be stored in
// outFile with permissions to write &/or truncate
outFile, err := os.OpenFile(fpath,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
f.Mode())
// again if there is any error this block
// will be executed and process
// will return to main function
if err != nil {
// with filenames gathered so far
// and err message
return filenames, err
}
rc, err := f.Open()
// again if there is any error this block
// will be executed and process
// will return to main function
if err != nil {
// with filenames gathered so far
// and err message back to main function
return filenames, err
}
_, err = io.Copy(outFile, rc)
// Close the file without defer so that
// it closes the outfile before the loop
// moves to the next iteration. this kinda
// saves an iteration of memory & time in
// the worst case scenario.
outFile.Close()
rc.Close()
// again if there is any error this block
// will be executed and process
// will return to main function
if err != nil {
// with filenames gathered so far
// and err message back to main function
return filenames, err
}
}
// Finally after every file has been appended
// into the filenames string[] and all the
// files have been extracted into the
// target directory, we return filenames
// and nil as error value as the process executed
// successfully without any errors*
// *only if it reaches until here.
return filenames, nil
}
My pwd path : ../src/myprograms/unzip and zip
Source zip folder : ../src/myprograms/unzip and zip/compression-test.zip
Compression-test.zip contains : Hello world.txt main.go
Destination path : ../src/myprograms/unzip and zip/uncompressed files
Output on my screen:
Unzipped the following files:
uncompressed files\compression-test\Hello world.txt
uncompressed files\compression-test\main.go
Visual Demo on Visual Studio Code:
Similar Reads
How to Rename and Move a File in Golang? In the Go language, you are allowed to rename and move the existing file to a new path with the help of the Rename() method. This method is used to rename and move a file from the old path to the new path. If the given new path already exists and it is not in a directory, then this method will repla
2 min read
How to Read a CSV File in Golang? Golang offers a vast inbuilt library that can be used to perform read and write operations on files. To read a CSV file, the following methods are used in Golang: os.Open(): The os.Open() method opens the named file for reading. This method returns either the os.File pointer or an error. encoding/cs
4 min read
How to Read and Write the Files in Golang? Golang offers a vast inbuilt library that can be used to perform read and write operations on files. In order to read from files on the local system, the io/ioutil module is put to use. The io/ioutil module is also used to write content to the file. This revised version reflects the changes made in
4 min read
How to Delete or Remove a File in Golang? In the Go language, you are allowed to remove the existing file with the help of the Remove() method. This method removes the specified file from the director or it also removes empty directories. If the given path is incorrect, then it will throw an error of type *PathError. It is defined under the
1 min read
How to Read File Word By Word in Golang? File reading is such an important aspect of a programming language. We need to perform certain operations programmatically, using automation in file reading/writing allows us to create certain programs/projects which might have looked impossible otherwise. File InputTo work with files, we have to in
5 min read
How to Create an Empty File in Golang? Like other programming languages, Go language also allows you to create files. For creating a file it provides Create() function, this function is used to create or truncates the given named file. This method will truncate the file, if the given file is already exists. This method will create a file
2 min read