Faisons une liste compatible Go 1 de toutes les façons de lire et d'écrire des fichiers dans Go.
Parce que l'API de fichiers a changé récemment et la plupart des autres réponses ne fonctionnent pas avec Go 1. Ils manquent également bufio
ce qui est important à mon humble avis.
Dans les exemples suivants, je copie un fichier en le lisant et en l'écrivant dans le fichier de destination.
Commencez avec les bases
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)
}
}
}
Ici, j'ai utilisé os.Open
et os.Create
qui sont des emballages pratiques autour os.OpenFile
. Nous n'avons généralement pas besoin d'appeler OpenFile
directement.
Remarquez le traitement de l'EOF. Read
essaie de répondre buf
à chaque appel et retourne io.EOF
comme erreur s'il atteint la fin du fichier. Dans ce cas buf
, conservera toujours les données. Les appels ultérieurs à Read
renvoie zéro comme le nombre d'octets lus et identique io.EOF
à l'erreur. Toute autre erreur entraînera une panique.
En utilisant 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
agit simplement comme un tampon ici, car nous n'avons pas grand-chose à voir avec les données. Dans la plupart des autres situations (spécialement avec les fichiers texte), bufio
c'est très utile en nous donnant une belle API pour lire et écrire facilement et de manière flexible, tout en gérant la mise en mémoire tampon en arrière-plan.
En utilisant 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)
}
}
C'est de la tarte! Mais utilisez-le uniquement si vous êtes sûr que vous ne traitez pas avec de gros fichiers.
panic("error in writing")
) n'est donc pas nécessaire.C'est une bonne version:
la source
0x777
est faux. Dans tous les cas, il devrait ressembler davantage à0644
ou0755
(octal, pas hex).En utilisant
io.Copy
Si vous n'avez pas envie de réinventer la roue, le
io.Copy
etio.CopyN
peut bien vous servir. Si vous vérifiez la source de la fonction io.Copy, ce n'est rien d'autre qu'une des solutions de Mostafa (la «basique», en fait) packagée dans la bibliothèque Go. Cependant, ils utilisent un tampon beaucoup plus grand que lui.la source
w.Sync()
après leio.Copy(w, r)
io.Copy()
n'écrira que les données avec lesquelles vous l'alimentez, donc si le fichier existant avait plus de contenu, il ne sera pas supprimé, ce qui peut entraîner la corruption du fichier.w, err := os.Create("output.txt")
, ce que vous décrivez ne se produit pas, car «Créer crée ou tronque le fichier nommé. Si le fichier existe déjà, il est tronqué». golang.org/pkg/os/#Create .Avec les nouvelles versions de Go, la lecture / écriture vers / depuis un fichier est facile. Pour lire à partir d'un fichier:
Pour écrire dans un fichier:
Cela écrasera le contenu d'un fichier (créez un nouveau fichier s'il n'y était pas).
la source
[]byte
est une tranche (similaire à une sous-chaîne) de tout ou partie d'un tableau d'octets. Considérez la tranche comme une structure de valeurs avec un champ de pointeur caché pour que le système puisse localiser et accéder à tout ou partie d'un tableau (la tranche), plus des champs pour la longueur et la capacité de la tranche, auxquels vous pouvez accéder à l'aide des fonctionslen()
etcap()
.Voici un kit de démarrage fonctionnel pour vous, qui lit et imprime un fichier binaire; vous devrez modifier la
inName
valeur littérale pour faire référence à un petit fichier sur votre système.la source
if
blocEssaye ça:
la source
En regardant simplement la documentation, il semble que vous devez simplement déclarer un tampon de type [] octet et le passer à read qui lira ensuite autant de caractères et retournera le nombre de caractères réellement lus (et une erreur).
Les docs disent
Ça ne marche pas?
EDIT: Aussi, je pense que vous devriez peut-être utiliser les interfaces Reader / Writer déclarées dans le paquet bufio au lieu d'utiliser le paquet os .
la source
La méthode Read prend un paramètre d'octet car c'est le tampon dans lequel il lira. C'est un idiome courant dans certains cercles et a un sens lorsque vous y pensez.
De cette façon, vous pouvez déterminer combien d'octets seront lus par le lecteur et inspecter le retour pour voir combien d'octets ont réellement été lus et gérer les erreurs de manière appropriée.
Comme d'autres l'ont souligné dans leurs réponses, bufio est probablement ce que vous voulez pour lire dans la plupart des fichiers.
J'ajouterai un autre indice car c'est vraiment utile. Il est préférable de lire une ligne à partir d'un fichier non pas par la méthode ReadLine mais par la méthode ReadBytes ou ReadString à la place.
la source