Hagamos una lista compatible con Go 1 de todas las formas de leer y escribir archivos en Go.
Debido a que la API de archivo ha cambiado recientemente y la mayoría de las otras respuestas no funcionan con Go 1. También omiten lo bufio
que es importante en mi humilde opinión.
En los siguientes ejemplos, copio un archivo leyéndolo y escribiendo en el archivo de destino.
Comience con lo 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)
}
}
}
Aquí utilicé os.Open
y os.Create
que son envoltorios convenientes alrededor os.OpenFile
. Por lo general, no necesitamos llamar OpenFile
directamente.
Aviso de tratamiento de EOF. Read
intenta completar buf
cada llamada y devuelve un io.EOF
error si llega al final del archivo al hacerlo. En este caso buf
aún se conservarán los datos. Las llamadas consiguientes a Read
devuelve cero como el número de bytes leídos e igual io.EOF
que el error. Cualquier otro error provocará pánico.
Utilizando 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
solo está actuando como un búfer aquí, porque no tenemos mucho que ver con los datos. En la mayoría de las otras situaciones (especialmente con archivos de texto) bufio
es muy útil al proporcionarnos una buena API para leer y escribir de manera fácil y flexible, mientras maneja el almacenamiento en búfer detrás de escena.
Utilizando 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)
}
}
¡Muy fácil! Pero úselo solo si está seguro de que no está tratando con archivos grandes.