Go language provides
os package for using operating system services and that includes file handling.
Let's go through a step by step process and learn how to open files and read and write to them in Go Lang.
Opening a file
Go provides two function calls,
Open() and
OpenFile(), to open a file. Here is the function declaration of these two:-
func Open(name string) (*File, error)
func OpenFile(name string, flag int, perm FileMode) (*File, error)
Open() takes the name of the file to open as an argument and returns a file handle ( or object ) and error if there is any.The thing we have to keep in mind is that when we open a file using
Open() function call, it opens in a read-only mode. So you can only read from the file and not write to it. To be able to write to a file, we would have to use the
OpenFile() function.
To start with let's use the
Open() call to get a hang of it. Here's the program for it.
package main
import (
"fmt"
"os"
)
func main() {
filehandle,err := os.Open("hello.txt")
if err == nil {
fmt.Println("File Opened successfully", filehandle)
} else {
fmt.Println("Error :", err)
}
}
So, I created a file named
hello.txt in the same directory as my Go program and then ran this program. In the above program, we import the package
os that provides us with OS interface. We call the
Open() function and check for error. If there is no error, we print the file handle, which is basically some number.
Reading from a file
So that was a pretty basic example. Now let's try to read something from the opened file. For that we will use the following function call provided by
os package.
func (f *File) Read(b []byte) (n int, err error)
Read() function takes as an input an array of bytes,
b, into which it will fill whatever it reads from the file. It returns the number of bytes it read from the file,
n, and error if there was any.
Let's enhance the above program to read something from the file,
hello.txt.
package main
import (
"fmt"
"os"
)
func main() {
filehandle,err := os.Open("hello.txt")
b := make([]byte, 20)
if err == nil {
fmt.Println("File Opened successfully", filehandle)
n, err := filehandle.Read(b)
if err == nil {
fmt.Printf("Read Success. N=[%d], Text=[%s]", n, b)
} else {
fmt.Println("Read Error:",err)
}
} else {
fmt.Println("Error :", err)
}
}
So we added a byte array,
b, that is allocated a space of 20 bytes. We called
Read() function using the file handle that we received when we opened the file using
Open(), and then we printed whatever we read from the file in case there was no error.
Writing to a file
So that was pretty simple, I hope. Opening and Reading from a file in Go is quite straightforward. Now, let's explore how to write to a file.
Remember that
Open() function opens a file in read-only mode. To be able to write to a file, we need to use
OpenFile() function. First, let's understand how to use the
OpenFile() function.
func OpenFile(name string, flag int, perm FileMode) (*File, error)
The first argument of the
OpenFile() is the name of the file that we would like to open.
Next is an integer called flag. flag can take one of the following values.
const (
// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
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 to the file when writing.
O_CREATE int = syscall.O_CREAT //createnew 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 file when opened.
)
So, if we would open a file for read-only purpose, the value of the flag will be
O_RDONLY. If we open a file for only writing, then flag shall be
O_WRONLY and so on.
As documentation above suggests, flag can only have either one of the following values
O_RDONLY, O_WRONLY, O_RDWR. The rest of the values in the above block can be ORed with any of the first three, depending on the requirement.
For example,
If we wanted to open the file for Reading and writing, and we wanted that when we write to the file, the data should be appended to it, we would have the value of flag as
O_RDWR | O_APPEND.
And if we wanted to want to open a file for writing and if the file does not exist we would like have it created, the value of the flag would be
O_WRONLY | O_CREATE
Next Argument,
perm, is of type
FileMode. This argument defines the kind of permissions that this file has and what kind of file it is. It is a 32 bit integer, where the least significant 9 bits, represent the standard unix permissions like rwxrwxrwx. So, while creating the file you can specify the kind of permissions that this file is going to be created with.
The Other bits in the
FileMode have their own significance, but we will not cover them in this lesson.
So, now that we have understood each argument of the
FileOpen() function, now let's write a short program, that will write some text to a file.
To write to a file, we shall use the
Write() function.
func (f *File) Write(b []byte) (n int, err error)
The
Write() function, takes a byte array as an argument and writes the contents of this byte array to the file. It returns the number of bytes written to file and error if there is any.
Here's the program that depicts usage of
FileOpen() and
Write().
package main
import (
"fmt"
"os"
)
func main() {
f, err := os.OpenFile("gotest.txt",os.O_RDWR|os.O_CREATE,0777)
if err == nil {
fmt.Println("File Opened for writing successfully")
b := []byte("Hello there")
n,err := f.Write(b)
if err == nil {
fmt.Printf("Written %d bytes successfully",n)
} else {
fmt.Println("Error in Writing to file",err)
}
} else {
fmt.Println("Error in Opening file", err)
}
}
In the above program, we opened a file "gotest.txt" with flag
O_RDWR | O_CREATE and file permission as 0777. We wrote a byte array containing the text "Hello there" to the file. We check for error as always before declaring success.
Well, that is it for this lesson. We shall see other File Handling related functions provided by
os package in the next lesson.
Part 2 of this lesson is now available.
References: