Crie um io.Reader a partir de um arquivo local

89

Eu gostaria de abrir um arquivo local e retornar a io.Reader. O motivo é que preciso alimentar um io.Readerpara uma biblioteca que estou usando, como:

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

}
Xi 张 熹
fonte
1
Provavelmente vale a pena gastar algum tempo navegando em golang.org/pkg e, pelo tipo de coisa que parece que você está fazendo, os, io, io / ioutil e bufio.
twotwotwo

Respostas:

117

os.Open retorna um 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
fonte
30
Ei, adorei o truque de mostrar que (* os.File) é um io.Reader sem ser capaz de abrir arquivos do Playground.
twotwotwo
@twotwotwo o que exatamente esse hack faz. Estou assumindo sintaticamente que ele está dizendo um arquivo de nada, então nunca tenta abrir nada.
mschuett de
7
@mschuett Mais ou menos: é um nilponteiro do tipo certo para apontar para um os.File. (Nesse caso, você não pode realmente fazer nada por meio dele.) E a var _ io.Reader = (*os.File)(nil)atribuição faz o compilador verificar se *os.Fileé um io.Reader(ou a atribuição não seria válida). Se você for ao Playground e mudar *os.Filepara, *os.Processverá o erro que ele gera para coisas que não satisfazem a interface.
twotwotwo de
2
@fabrizioM onde exatamente na documentação diz que * os.File implementa um Reader. Caso contrário, sem essa resposta, como você poderia descobrir a si mesmo apenas lendo um documento oficial? Ok, eu vejo isso func (f *File) Read(b []byte) (n int, err error), o mesmo que em Reader.
Aliaksandr Kazlou de
43

Use os.Open () :

função Open (name string) (file * File, err error)

Abrir abre o arquivo nomeado para leitura. Se for bem-sucedido, os métodos do arquivo retornado podem ser usados ​​para leitura; o descritor de arquivo associado tem o modo O_RDONLY. Se houver um erro, será do tipo * PathError.

O valor retornado do tipo *os.Fileimplementa a io.Readerinterface.

ANisus
fonte
27

O tipo * os.File implementa a interface io.Reader, para que você possa retornar o arquivo como um Leitor. Mas eu recomendo que você use o pacote bufio se você tiver intenções de ler arquivos grandes, algo assim:

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

return bufio.NewReader(file)
Yandry Pozo
fonte
4
Você poderia explicar por que você recomenda bufiopara arquivos grandes?
Ciro Costa
1
@CiroCosta se você tem um arquivo enorme de Gbs que não quer ler completamente na memória, então para esses casos devemos usar um buffer
Yandry Pozo
O tempo de execução de go usa buffers em situações sensíveis, por exemplo, io.Copy irá reutilizar buffers subjacentes se sua interface estiver disponível - caso contrário, ele criará um buffer interno
colm.anseo
1
Obrigado por path/file.ext. Nenhuma outra resposta esclareceu o que os.Fileera.
Azurespot
5

Aqui está um exemplo em que abrimos um arquivo de texto e criamos um io.Reader a partir da instância * os.File f retornada

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
}
éter espacial
fonte