Golang File Handling

Handle files with the bufio type, NewScanner, Scan and Text. Read the lines of a text file.

File. A file contains many lines. In Go we can use the bufio package to read in all the lines in this file inside a loop. With Scan and Text we get a string for each line.

With bufio, we have many helpful methods for handling text files. Newlines are handled automatically. The classes are easy to use with some practice.

First example. This program opens a file on the disk. Please change the path argument to os.Open to a file that exists on your computer. Errors are not handled here.
Open: This returns a *File descriptor. We can pass the result of Open() to the bufio.NewScanner method.
NewScanner: This creates a new *Scanner. The File we pass to this method is accessed through its Reader interface.
Scan: This advances to the next part of the file and returns true if there is more data. And text() creates a string from the current line.
Golang program that uses bufio, reads text file package main import ( "bufio" "fmt" "os" ) func main() { // Open the file. f, _ := os.Open("C:\\programs\\file.txt") // Create a new Scanner for the file. scanner := bufio.NewScanner(f) // Loop over all lines in the file and print them. for scanner.Scan() { line := scanner.Text() fmt.Println(line) } } Output Carrot Bird Fish Turnip Contents of file.txt Carrot Bird Fish Turnip

ScanWords. A file sometimes contains words. We can get each word separately as a string with the Scan() and Text() methods. First we must call Split.
Tip: The Split method here just sets the splitting method for the scanner. It influences the behavior of Scan().
Golang program that uses bufio.ScanWords, gets words package main import ( "bufio" "fmt" "os" ) func main() { f, _ := os.Open("C:\\programs\\file.txt") scanner := bufio.NewScanner(f) // Set the Split method to ScanWords. scanner.Split(bufio.ScanWords) // Scan all words from the file. for scanner.Scan() { line := scanner.Text() fmt.Println(line) } } Output a commodius vicus of recirculation Contents of file.txt a commodius vicus of recirculation

Read entire file. With ioutil.ReadAll we can get the entire contents of a file in a byte slice or a string. We must import "io/ioutil" and then call ioutil.ReadAll on a reader.
NewReader: We use bufio.NewReader to create a buffered text file reader. We can then pass this to ReadAll.
ReadAll: This func returns a byte slice. We can convert the byte slice into a string—this makes it easier to display.
Golang program that uses ioutil.ReadAll package main import ( "bufio" "fmt" "io/ioutil" "os" ) func main() { // Open a file. f, _ := os.Open("C:\\programs\\file.txt") // Use bufio.NewReader to get a Reader. // ... Then use ioutil.ReadAll to read the entire content. reader := bufio.NewReader(f) content, _ := ioutil.ReadAll(reader) // File content. fmt.Println(string(content)) } Output This is an example file. With two lines. Contents of file.txt: This is an example file. With two lines.

File exists. Does a file or directory exist? We test 2 paths that likely point to no files or directories. We invoke os.Stat on the path strings, and store the error in "err."
Then: We pass the error variable to os.IsNotExist. We test the result in an if-statement.
Tip: The os.IsNotExist func will work on both files and directories. If no error is returned, it will return false.
Golang program that uses Stat, os.IsNotExist package main import ( "fmt" "os" ) func main() { directory := "/home/none/lost" _, err := os.Stat(directory) // See if directory exists. // ... Use the IsNotExist method. if os.IsNotExist(err) { fmt.Println("Directory does not exist") } file := "/home/none/program.go" _, err = os.Stat(file) // See if the file exists. if os.IsNotExist(err) { fmt.Println("File does not exist") } } Output Directory does not exist File does not exist

Get file size. Sometimes we wish to get the size in bytes of a file. We can call os.Stat and then the Size() method. This returns the count of bytes in the file.
Golang program that uses Stat and Size package main import ( "fmt" "os" ) func main() { file := "C:\\programs\\program.go" // Call Stat on a path string to get statistics. stat, _ := os.Stat(file) // Get file size. size := stat.Size() fmt.Println("FILE SIZE IN BYTES:", size) } Output FILE SIZE IN BYTES: 310

Move file. How can we rename or move a file? We must import the "os" package, which contains many helpful file-system funcs. In main(), we have "before" and "after" locations.
Tip: We want to move the file from the before, to the after, location. We pass the 2 arguments to os.Rename.
Result: We find (by examining the files in the file manager) that the file has been moved (renamed).
Golang program that uses os.Rename, moves a file package main import ( "fmt" "os" ) func main() { before := "/home/sam/test.txt" after := "/home/sam/optimized.txt" // Rename or move file from one location to another. os.Rename(before, after) fmt.Println("DONE") } Output DONE

Write file. With ioutil, we can call WriteFile to write a byte slice to a file. For a text file, we can also use NewWriter and WriteString.WriteFile

Copy file. We cannot use os.Rename to copy a file, as it just moves a file. Instead we must use ioutil.ReadAll to read in the contents, and then write them in a new location.Copy File

Import os. In the "os" package we find many helpful methods. With the os.Remove() func we can delete a file. With os.Open we can invoke Readdir to get all file names in a directory.os.RemoveReaddir

Compression. With the "compress" package we can compress byte data and strings to gzip files. We use the NewWriter method to begin writing compressed data.compress

CSV files. With the "encoding/csv" package we can parse fields in a CSV file without using Split() calls. This makes reading comma-separated values easier.csv

In file handling, errors are common and often unavoidable. We use the error return value from os.Open, and the recover() method, to handle these events.

© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.