Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read/write from/to a file using Go

Tags:

file

go

I've been trying to learn Go on my own, but I've been stumped on trying read from and write to ordinary files.

I can get as far as inFile, _ := os.Open(INFILE, 0, 0), but actually getting the content of the file doesn't make sense, because the read function takes a []byte as a parameter.

func (file *File) Read(b []byte) (n int, err Error) 
like image 523
Seth Hoenig Avatar asked Nov 30 '09 19:11

Seth Hoenig


People also ask

How do you write data into a file in go?

Go write to file with ioutil.The outil. WriteFile writes data to the specified file. This is a higher-level convenience function. The opening and closing of the file is handled for us.

How do I read and write 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.

How do I read a text file in go?

The simplest way of reading a text or binary file in Go is to use the ReadFile() function from the os package. This function reads the entire content of the file into a byte slice, so you should be careful when trying to read a large file - in this case, you should read the file line by line or in chunks.

How do you create a text file in Golang?

In the main() function, we created a file "Sample. txt" using os. Create() function and write text data into file using WriteString() file. The WriteString() function returns the number of characters written into the file.


1 Answers

Let's make a Go 1-compatible list of all the ways to read and write files in Go.

Because file API has changed recently and most other answers don't work with Go 1. They also miss bufio which is important IMHO.

In the following examples I copy a file by reading from it and writing to the destination file.

Start with the basics

package main  import (     "io"     "os" )  func main() {     // open input file     fi, err := os.Open("input.txt")     if err != nil {         panic(err)     }     // close fi on exit and check for its returned error     defer func() {         if err := fi.Close(); err != nil {             panic(err)         }     }()      // open output file     fo, err := os.Create("output.txt")     if err != nil {         panic(err)     }     // close fo on exit and check for its returned error     defer func() {         if err := fo.Close(); err != nil {             panic(err)         }     }()      // make a buffer to keep chunks that are read     buf := make([]byte, 1024)     for {         // read a chunk         n, err := fi.Read(buf)         if err != nil && err != io.EOF {             panic(err)         }         if n == 0 {             break         }          // write a chunk         if _, err := fo.Write(buf[:n]); err != nil {             panic(err)         }     } } 

Here I used os.Open and os.Create which are convenient wrappers around os.OpenFile. We usually don't need to call OpenFile directly.

Notice treating EOF. Read tries to fill buf on each call, and returns io.EOF as error if it reaches end of file in doing so. In this case buf will still hold data. Consequent calls to Read returns zero as the number of bytes read and same io.EOF as error. Any other error will lead to a panic.

Using bufio

package main  import (     "bufio"     "io"     "os" )  func main() {     // open input file     fi, err := os.Open("input.txt")     if err != nil {         panic(err)     }     // close fi on exit and check for its returned error     defer func() {         if err := fi.Close(); err != nil {             panic(err)         }     }()     // make a read buffer     r := bufio.NewReader(fi)      // open output file     fo, err := os.Create("output.txt")     if err != nil {         panic(err)     }     // close fo on exit and check for its returned error     defer func() {         if err := fo.Close(); err != nil {             panic(err)         }     }()     // make a write buffer     w := bufio.NewWriter(fo)      // make a buffer to keep chunks that are read     buf := make([]byte, 1024)     for {         // read a chunk         n, err := r.Read(buf)         if err != nil && err != io.EOF {             panic(err)         }         if n == 0 {             break         }          // write a chunk         if _, err := w.Write(buf[:n]); err != nil {             panic(err)         }     }      if err = w.Flush(); err != nil {         panic(err)     } } 

bufio is just acting as a buffer here, because we don't have much to do with data. In most other situations (specially with text files) bufio is very useful by giving us a nice API for reading and writing easily and flexibly, while it handles buffering behind the scenes.


Note: The following code is for older Go versions (Go 1.15 and before). Things have changed. For the new way, take a look at this answer.

Using ioutil

package main  import (     "io/ioutil" )  func main() {     // read the whole file at once     b, err := ioutil.ReadFile("input.txt")     if err != nil {         panic(err)     }      // write the whole body at once     err = ioutil.WriteFile("output.txt", b, 0644)     if err != nil {         panic(err)     } } 

Easy as pie! But use it only if you're sure you're not dealing with big files.

like image 136
Mostafa Avatar answered Oct 03 '22 05:10

Mostafa