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 bufioque 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.Openy os.Createque son envoltorios convenientes alrededor os.OpenFile. Por lo general, no necesitamos llamar OpenFiledirectamente.
Aviso de tratamiento de EOF. Readintenta completar bufcada llamada y devuelve un io.EOFerror si llega al final del archivo al hacerlo. En este caso bufaún se conservarán los datos. Las llamadas consiguientes a Readdevuelve cero como el número de bytes leídos e igual io.EOFque 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)
}
}
bufiosolo 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) bufioes 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.
panic("error in writing")) no es necesaria.Esta es una buena versión:
fuente
0x777es falso. En cualquier caso, debería ser más como0644o0755(octal, no hexadecimal).Utilizando
io.CopySi no tiene ganas de reinventar la rueda, el
io.Copyyio.CopyNpuede servir bien. Si verifica el origen de la función io.Copy, no es más que una de las soluciones de Mostafa (la 'básica', en realidad) empaquetada en la biblioteca Go. Sin embargo, están usando un buffer significativamente más grande que él.fuente
w.Sync()después de laio.Copy(w, r)io.Copy()solo escribirá los datos con los que lo alimente, por lo que si el archivo existente tenía más contenido, no se eliminará, lo que puede provocar un archivo dañado.w, err := os.Create("output.txt"), lo que describe no sucede porque "Crear crea o trunca el archivo con nombre. Si el archivo ya existe, se trunca". golang.org/pkg/os/#Create .Con las versiones más nuevas de Go, leer / escribir en / desde el archivo es fácil. Para leer de un archivo:
Para escribir en un archivo:
Esto sobrescribirá el contenido de un archivo (cree un nuevo archivo si no estaba allí).
fuente
[]bytees un segmento (similar a una subcadena) de todo o parte de una matriz de bytes. Piense en el segmento como una estructura de valores con un campo de puntero oculto para que el sistema ubique y acceda a todo o parte de una matriz (el segmento), más campos para la longitud y la capacidad del segmento, a los que puede acceder utilizando las funcioneslen()ycap().Aquí hay un kit de inicio que funciona para usted, que lee e imprime un archivo binario; necesitará cambiar el
inNamevalor literal para referirse a un pequeño archivo en su sistema.fuente
ifbloquePrueba esto:
fuente
Simplemente mirando la documentación, parece que debería declarar un búfer de tipo [] byte y pasarlo a leer que luego leerá hasta tantos caracteres y devolverá el número de caracteres realmente leídos (y un error).
Los documentos dicen
¿Eso no funciona?
EDITAR: Además, creo que quizás debería usar las interfaces Reader / Writer declaradas en el paquete bufio en lugar de usar el paquete os .
fuente
El método de lectura toma un parámetro de byte porque es el búfer en el que leerá. Es un idioma común en algunos círculos y tiene sentido cuando lo piensas.
De esta manera, puede determinar cuántos bytes leerá el lector e inspeccionar el retorno para ver cuántos bytes se leyeron realmente y manejar los errores de manera adecuada.
Como otros han señalado en sus respuestas, bufio es probablemente lo que desea leer de la mayoría de los archivos.
Agregaré otra pista ya que es realmente útil. La mejor forma de leer una línea de un archivo no es mediante el método ReadLine, sino el método ReadBytes o ReadString.
fuente