Facciamo un elenco compatibile con Go 1 di tutti i modi per leggere e scrivere file in Go.
Poiché l'API dei file è cambiata di recente e la maggior parte delle altre risposte non funziona con Go 1. Hanno anche perso l' bufio
IMHO importante.
Negli esempi seguenti copio un file leggendo da esso e scrivendo nel file di destinazione.
Inizia con le basi
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)
}
}
}
Qui ho usato os.Open
e os.Create
quali sono i wrapper convenienti in giro os.OpenFile
. Di solito non abbiamo bisogno di chiamare OpenFile
direttamente.
Si noti il trattamento di EOF. Read
tenta di riempire buf
ogni chiamata e restituisce io.EOF
come errore se raggiunge la fine del file. In questo caso buf
manterrà comunque i dati. Le chiamate successive a Read
restituiscono zero come numero di byte letti e uguale io.EOF
a errore. Qualsiasi altro errore porterà ad un panico.
utilizzando 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
agisce solo come buffer qui, perché non abbiamo molto a che fare con i dati. Nella maggior parte delle altre situazioni (specialmente con file di testo) bufio
è molto utile dandoci una bella API per leggere e scrivere facilmente e in modo flessibile, mentre gestisce il buffering dietro le quinte.
utilizzando 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)
}
}
Facile come una torta! Ma usalo solo se sei sicuro di non avere a che fare con file di grandi dimensioni.