Cree un io.Reader desde un archivo local

85

Me gustaría abrir un archivo local y devolver un io.Reader. La razón es que necesito alimentar io.Readera una biblioteca que estoy usando, como:

func read(r io.Reader) (results []string) {

}
Xi 张 熹
fuente
1
Probablemente valga la pena pasar un tiempo navegando por golang.org/pkg y, por el tipo de cosas que parece que estás haciendo, os, io, io / ioutil y bufio.
twotwotwo

Respuestas:

112

os.Open devuelve un io.Reader

http://play.golang.org/p/BskGT09kxL

package main

import (
    "fmt"
    "io"
    "os"
)

var _ io.Reader = (*os.File)(nil)

func main() {
    fmt.Println("Hello, playground")
}
fabrizioM
fuente
30
Je, me encanta el truco para demostrar que (* os.File) es un io.Reader sin poder abrir archivos desde Playground.
veces dos
@twotwotwo ¿qué hace exactamente ese truco? Supongo que sintácticamente está diciendo un archivo de nada, por lo que nunca intenta abrir nada.
mschuett
7
@mschuett Más o menos: es un nilpuntero del tipo correcto para apuntar a un os.File. (En este caso, realmente no puede hacer nada a través de él). Y la var _ io.Reader = (*os.File)(nil)asignación hace que el compilador compruebe que *os.Filees an io.Reader(o de lo contrario la asignación no sería válida). Si va al patio de juegos y cambia *os.Filea *os.Process, verá el error que genera para las cosas que no satisfacen la interfaz.
twotwotwo
2
@fabrizioM donde exactamente en la documentación dice que * os.File implementa un Reader. De lo contrario, sin esta respuesta, ¿cómo podría entenderse con solo leer un documento oficial? Ok, veo eso func (f *File) Read(b []byte) (n int, err error), lo mismo que en Reader.
Aliaksandr Kazlou
42

Utilice os.Open () :

func Open (cadena de nombre) (archivo * Archivo, error err)

Abrir abre el archivo con nombre para su lectura. Si tiene éxito, los métodos del archivo devuelto se pueden usar para leer; el descriptor de archivo asociado tiene el modo O_RDONLY. Si hay un error, será de tipo * PathError.

El valor devuelto de tipo *os.Fileimplementa la io.Readerinterfaz.

ANiso
fuente
26

El tipo * os.File implementa la interfaz io.Reader, por lo que puede devolver el archivo como Reader. Pero te recomiendo que uses el paquete bufio si tienes intenciones de leer archivos grandes, algo como esto:

file, err := os.Open("path/file.ext")
// if err != nil { ... }

return bufio.NewReader(file)
Yandry Pozo
fuente
4
¿Podría explicar por qué lo recomienda bufiopara archivos grandes?
Ciro Costa
1
@CiroCosta, si tiene un archivo enorme de Gbs, no desea leerlo completamente en la memoria, por lo que para esos casos debemos usar un búfer
Yandry Pozo
El tiempo de ejecución de go usa búferes en situaciones sensibles, por ejemplo, io . Copiar reutilizará búferes subyacentes si su interfaz está disponible; de ​​lo contrario, creará un búfer interno
colm.anseo
1
Gracias por path/file.ext. Ninguna otra respuesta explicó lo que os.Fileera.
Azurespot
5

Aquí hay un ejemplo en el que abrimos un archivo de texto y creamos un io.Reader a partir de la instancia * os.File devuelta f

package main

import (
    "io"
    "os"
)

func main() {
    f, err := os.Open("somefile.txt")
    if err != nil {
        panic(err)
    }
    defer f.Close()

    var r io.Reader
    r = f
}
otro espacio
fuente