Getting started with golang os.File
In this tutorial, I will demonstrate how to work with files in Golang. We read files, write to them, create new ones, list them, and calculate their size and modification time. In Go, we use the os
package and type File
to work with files:
Package os provides a platform-independent interface to operating system functionality. The design is Unix-like, although the error handling is Go-like; failing calls return values of type error rather than error numbers. Often, more information is available within the error. For example, if a call that takes a file name fails, such as Open or Stat, the error will include the failing file name when printed and will be of type *PathError, which may be unpacked for more information.
type File:
type File struct {
// contains filtered or unexported fields
}
Some related functions to work with files:
func Create(name string) (*File, error)
func NewFile(fd uintptr, name string) *File
func Open(name string) (*File, error)
func OpenFile(name string, flag int, perm FileMode) (*File, error)
func (f *File) Chmod(mode FileMode) error
func (f *File) Chown(uid, gid int) error
func (f *File) Close() error
func (f *File) Read(b []byte) (n int, err error)
func (f *File) ReadAt(b []byte, off int64) (n int, err error)
func (f *File) Stat() (FileInfo, error)
func (f *File) Write(b []byte) (n int, err error)
func (f *File) WriteString(s string) (n int, err error)
Create a new file in Golang (os.Create)
The os.Create
function creates or truncates the specified file. It is truncated if the file already exists. The file is generated in mode 0666 if it doesn't already exist. The example makes an empty file:
package main
import (
"fmt"
"log"
"os"
)
func main() {
file, err := os.Create("helloGoLinuxCloud.txt")
defer file.Close()
if err != nil {
log.Fatal(err)
}
fmt.Println("file created")
}
Output:
file created
Check file exists in Golang (os.Stat)
The sample that follows determines whether the specified file is present.
package main
import (
"errors"
"fmt"
"os"
)
func main() {
// check if file exists
_, err := os.Stat("words.txt")
if errors.Is(err, os.ErrNotExist) {
fmt.Println("file does not exist")
} else {
fmt.Println("file exists")
}
// check if file exists
_, err = os.Stat("helloGoLinuxCloud.txt")
if errors.Is(err, os.ErrNotExist) {
fmt.Println("file does not exist")
} else {
fmt.Println("file exists")
}
}
Output:
file does not exist
file exists
Delete file in Golang (os.Remove)
The function os.Remove
is used to delete the given file. The program will throw an error if file does not exist:
package main
import (
"fmt"
"log"
"os"
)
func main() {
err := os.Remove("helloGoLinuxCloud.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("file deleted")
}
Output:
// if file exists: file deleted // if file does not exist 2022/10/17 10:06:47 remove helloGoLinuxCloud.txt: The system cannot find the file specified. exit status 1
Get file size and last modified time in Golang
In the following example, we get the file size and last modified time:
package main
import (
"fmt"
"log"
"os"
)
func main() {
fileName := "helloGoLinuxCloud.txt"
// get file info
fileInfo, err := os.Stat(fileName)
if err != nil {
log.Fatal(err)
}
mTime := fileInfo.ModTime()
fmt.Println("Last modify time:", mTime)
fSize := fileInfo.Size()
fmt.Println("File size:", fSize)
}
Output:
Last modify time: 2022-10-17 10:11:20.6863946 +0700 +07
File size: 10
Read file in Golang
Read entire file into 1 variable
We can use ReadFile()
function to get the content of the file. Large files shouldn't be utilized with this function because it reads the entire file at once.
func ReadFile(name string) ([]byte, error)
: ReadFile reads the named file and returns the contents. A successful call returns err == nil
, not err == EOF
. Because ReadFile reads the whole file, it does not treat an EOF from Read as an error to be reported.
Here is an example of reading .txt
file. The content is []byte, so we can convert it to string or directly use os.Stdout.Write()
function to print out the content:
package main
import (
"fmt"
"log"
"os"
)
func main() {
content, err := os.ReadFile("./helloGoLinuxCloud.txt")
if err != nil {
log.Fatal(err)
}
// print out the content
os.Stdout.Write(content)
fmt.Println()
// convert to string
myString := string(content[:])
fmt.Println("After converting.....")
fmt.Println(myString)
}
Output:
Welcome to GolinuxCloud!
This is file example!
After converting.....
Welcome to GolinuxCloud!
This is file example!
Read line by line
Reading a large file line by line is a better approach. In this manner, the program uses less memory than usual.
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
f, err := os.Open("helloGoLinuxCloud.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
Output:
**Welcome To The World of Free Plain Vanilla Electronic Texts**
**eBooks Readable By Both Humans and By Computers, Since 1971**
*****These eBooks Were Prepared By Thousands of Volunteers!*****
Title: The Adventures of Sherlock Holmes
Author: Sir Arthur Conan Doyle
Release Date: March, 1999 [EBook #1661]
[Most recently updated: November 29, 2002]
Edition: 12
Language: English
Character set encoding: ASCII
*** START OF THE PROJECT GUTENBERG EBOOK, THE ADVENTURES OF SHERLOCK HOLMES ***
(Additional editing by Jose Menendez)
THE ADVENTURES OF
SHERLOCK HOLMES
BY
SIR ARTHUR CONAN DOYLE
Explanation:
- The
os.Open
function allows reading of the provided file. The attached file descriptor has mode O RDONLY, and if successful, the functions on the returned file can be used for reading. - TheÂ
bufio.NewScanner
 function returns a newÂScanner
to read from file. The Scan function proceeds by lines in the default mode.
Write/Append to a file in Golang
Write to a file
We can use WriteFile()
function to write data to a file:
func WriteFile(name string, data []byte, perm FileMode) error
: WriteFile writes data to the named file, creating it if necessary. If the file does not exist, WriteFile creates it with permissions perm (before umask); otherwise WriteFile truncates it before writing, without changing permissions.
package main
import (
"log"
"os"
)
func main() {
content := `This is example of file
You can open a file to see the content.`
err := os.WriteFile("./writeFile.txt", []byte(content), 0666)
if err != nil {
log.Fatal(err)
}
}
Output of writeFile.txt:
This is example of file
You can open a file to see the content.
Append to a file
We add the os.O_APPEND
flag to the os.OpenFile
function's flags in order to append data to a file. Here is an example of appending to a .txt file
package main
import (
"log"
"os"
)
func main() {
// If the file doesn't exist, create it, or append to the file
file, err := os.OpenFile("writeFile.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
appendContent := `
This line is appended to existed file`
if _, err := file.Write([]byte(appendContent)); err != nil {
file.Close() // ignore error; Write error takes precedence
log.Fatal(err)
}
if err := file.Close(); err != nil {
log.Fatal(err)
}
}
Output of writeFile.txt:
This is example of file
You can open a file to see the content.
This line is appended to existed file
Summary
In this article, I have given examples of working with files in Golang. With the use of the os
package, working with file is quite simple and straightforward.
References
https://pkg.go.dev/os
https://en.wikipedia.org/wiki/Text_file