How to Read and Write a File in Golang?
Table of Contents
In this tutorial, we will learn how to read and write files in the file system using the io/ioutil
package.
Write a file using WriteFile #
The WriteFile
function takes 3 arguments, filename, data in a byte array, and filemode.
func WriteFile(filename string, data []byte, perm os.FileMode) error
A FileMode represents a file’s mode and permission bits. Learn more
package main
import (
"io/ioutil"
"log"
)
func main() {
// create a byte array of a string
data := []byte("Hello Gopher!")
// write data to a hello file, with 0777 file permission
err := ioutil.WriteFile("hello.txt", data, 0777)
if err != nil {
log.Fatalf("%v", err)
}
}
This will create a new file hello.txt
in the current directory.
File mode #
Most file systems have methods to assign permissions or access rights to specific users and groups of users. These permissions control the ability of the users to view, change, navigate, and execute the contents of the file system. – wikipedia
A few examples of filemode number notation.
0000 no permissions
0700 read, write, & execute only for owner
0770 read, write, & execute for owner and group
0777 read, write, & execute for owner, group and others
0111 execute
0222 write
0333 write & execute
0444 read
0555 read & execute
0666 read & write
0740 owner can read, write, & execute; group can only read; others have no permissions
Read a file using ReadFile #
The ReadFile
function reads the file by its filename and returns the file data in array of byte.
func ReadFile(filename string) ([]byte, error)
We will read the above created hello.txt
file. Please create a file if it is not created.
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
// read the hello.txt
content, err := ioutil.ReadFile("hello.txt")
if err != nil {
log.Fatalf("error while reading %v", err)
}
// convert the byte into string
fmt.Println(string(content))
}
Output
Hello Gopher!
Write to an existing file #
1. using ioutil #
First using ReadFile
, we will read the content and then we will append the new content.
package main
import (
"io/ioutil"
"log"
)
func main() {
// Read the content
content, err := ioutil.ReadFile("hello.txt")
if err != nil {
log.Fatalf("error while reading the file. %v", err)
}
// new content
newText := []byte("\nAppended text.")
// append the content
content = append(content, newText...)
// overwrite the content of hello.txt
err = ioutil.WriteFile("hello.txt", content, 0777)
if err != nil {
log.Fatalf("error while writing the file. %v", err)
}
}
The 3 dots after newText...
is a variadic argument. In simple terms it will extract all the array elements.
Learn more
For Example:
if a = [1,2,3,4]
func (a...) => func (1, 2, 3, 4)
2. using os package #
Using OpenFile in the os package we can open the file and append the data in it.
Package os provides a platform-independent interface to operating system functionality.
func OpenFile(name string, flag int, perm FileMode) (*File, error)
The flag parameter defines the operation on the file. The available flags are:
O_RDONLY int = syscall.O_RDONLY // open the file read-only.
O_WRONLY int = syscall.O_WRONLY // open the file write-only.
O_RDWR int = syscall.O_RDWR // open the file read-write.
// The remaining values may be or'ed in to control behavior.
O_APPEND int = syscall.O_APPEND // append data to the file when writing.
O_CREATE int = syscall.O_CREAT // create a new file if none exists.
O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist.
O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened.
Example
package main
import (
"log"
"os"
)
func main() {
// If the file doesn't exist, create it, or append to the file
file, err := os.OpenFile("hello.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0777)
if err != nil {
log.Fatalf("error while opening the file. %v", err)
}
// close the file once program execution complete
defer file.Close()
if _, err := file.Write([]byte("\nappended data")); err != nil {
log.Fatalf("error while writing the file. %v", err)
}
}
Read and Write a JSON file #
Reading and writing the JSON file requires to unmarshal and marshal the data respectively.
Learn more about How to use JSON in Golang
We are going to create a library object and a book object. The library stores the array of books.
type book struct {
Name string
Author string
}
type library struct {
Books []book
}
Create books and library
// create some books
books := []book{
{Name: "An Introduction to programming in Go", Author: "Caleb Doxsey"},
{Name: "Go in Action", Author: "William Kennedy"},
{Name: "The way to Go", Author: "IVO BALBAERT"},
}
// create the library with books
lib := library{Books: books}
Write JSON #
The library is in golang struct format. To convert it JSON we need to marshal it.
// marshal to json or convert to json
libJSON, _ := json.Marshal(lib)
Save it in library.json
// write to library.json
err := ioutil.WriteFile("library.json", libJSON, 0777)
if err != nil {
log.Fatalf("Error while writing a file %v", err)
}
Read JSON #
Read the library.json
.
// Read the file
content, err := ioutil.ReadFile("library.json")
if err != nil {
log.Fatalf("Error while reading a file %v", err)
}
The data is in byte. Unmarshal it to access the data.
// create a new library
var readLib library
// unmarshal the json to library
err = json.Unmarshal(content, &readLib)
if err != nil {
log.Fatalf("Error while unmarshal the content %v", err)
}
// print all the books
for i, book := range readLib.Books {
fmt.Printf("%v| Name: %-40s | Author: %s\n", i, book.Name, book.Author)
}
Output
0| Name: An Introduction to programming in Go | Author: Caleb Doxsey
1| Name: Go in Action | Author: William Kennedy
2| Name: The way to Go | Author: IVO BALBAERT
The output is formatted because we used a little string formatting.
In the Printf
, we have used %-40s
. 40
is the width. -
align the data to left.
Learn more about string formatting.
Width is measured in units of Unicode code points, that is, runes.
For most values, width is the minimum number of runes to output, padding the formatted form with spaces if necessary.
The complete code will look like this
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
)
type book struct {
Name string
Author string
}
type library struct {
Books []book
}
func main() {
// create some books
books := []book{
{Name: "An Introduction to programming in Go", Author: "Caleb Doxsey"},
{Name: "Go in Action", Author: "William Kennedy"},
{Name: "The way to Go", Author: "IVO BALBAERT"},
}
// create the library with books
lib := library{Books: books}
// marshal to json or convert to json
libJSON, _ := json.Marshal(lib)
// write to library.json
err := ioutil.WriteFile("library.json", libJSON, 0777)
if err != nil {
log.Fatalf("Error while writing a file %v", err)
}
// Read the file
content, err := ioutil.ReadFile("library.json")
if err != nil {
log.Fatalf("Error while reading a file %v", err)
}
// create a new library
var readLib library
// unmarshal the json to library
err = json.Unmarshal(content, &readLib)
if err != nil {
log.Fatalf("Error while unmarshal the content %v", err)
}
// print all the books
for i, book := range readLib.Books {
fmt.Printf("%v| Name: %-40s | Author: %s\n", i, book.Name, book.Author)
}
}
Update the existing JSON file #
We will use ioutil
for this. First, we will read library.json
and then we add a new book in it.
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
)
type book struct {
Name string
Author string
}
type library struct {
Books []book
}
func main() {
// Read the file
content, err := ioutil.ReadFile("library.json")
if err != nil {
log.Fatalf("Error while reading a file %v", err)
}
// create a new library
var readLib library
// unmarshal the json to library
err = json.Unmarshal(content, &readLib)
if err != nil {
log.Fatalf("Error while unmarshal the content %v", err)
}
// before update
fmt.Println("Before Update")
// print all the books
for i, book := range readLib.Books {
fmt.Printf("%v| Name: %-40s | Author: %s\n", i, book.Name, book.Author)
}
// Update
newBook := book{
Name: "Go Web Programming",
Author: "Sau Sheong Chang",
}
// append the new book
readLib.Books = append(readLib.Books, newBook)
// write the book
// marshal to json or convert to json
libJSON, err := json.Marshal(readLib)
if err != nil {
log.Fatalf("Error while marshal. %v", err)
}
// write to library.json
err = ioutil.WriteFile("library.json", libJSON, 0777)
if err != nil {
log.Fatalf("Error while writing a file %v", err)
}
// After Update
fmt.Println("After update")
// Read the file
content, err = ioutil.ReadFile("library.json")
if err != nil {
log.Fatalf("Error while reading a file %v", err)
}
// unmarshal the json to library
err = json.Unmarshal(content, &readLib)
if err != nil {
log.Fatalf("Error while unmarshal the content %v", err)
}
// print all the books
for i, book := range readLib.Books {
fmt.Printf("%v| Name: %-40s | Author: %s\n", i, book.Name, book.Author)
}
}
Output
Before Update
0| Name: An Introduction to programming in Go | Author: Caleb Doxsey
1| Name: Go in Action | Author: William Kennedy
2| Name: The way to Go | Author: IVO BALBAERT
After update
0| Name: An Introduction to programming in Go | Author: Caleb Doxsey
1| Name: Go in Action | Author: William Kennedy
2| Name: The way to Go | Author: IVO BALBAERT
3| Name: Go Web Programming | Author: Sau Sheong Chang