Vamos fazer uma lista compatível com Go 1 de todas as maneiras de ler e gravar arquivos no Go.
Como a API do arquivo foi alterada recentemente e a maioria das outras respostas não funciona com o Go 1. Eles também ignoram o bufio
que é importante no IMHO.
Nos exemplos a seguir, copio um arquivo lendo e escrevendo no arquivo de destino.
Comece com o básico
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)
}
}
}
Aqui eu usei os.Open
e os.Create
quais são embalagens convenientes ao redor os.OpenFile
. Normalmente, não precisamos ligar OpenFile
diretamente.
Aviso tratando EOF. Read
tenta preencher buf
cada chamada e retorna io.EOF
como erro se chegar ao final do arquivo ao fazê-lo. Nesse caso buf
, ainda manterá os dados. Chamadas consequentes para Read
retorna zero como o número de bytes lidos e o mesmo io.EOF
que erro. Qualquer outro erro levará a um pânico.
Usando 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
está apenas atuando como um buffer aqui, porque não temos muito a ver com dados. Na maioria das outras situações (especialmente com arquivos de texto)bufio
é muito útil, oferecendo uma boa API para leitura e gravação de maneira fácil e flexível, enquanto lida com o buffer nos bastidores.
Usando 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)
}
}
Fácil como torta! Mas use-o apenas se tiver certeza de que não está lidando com arquivos grandes.