Utwórz io.Reader z lokalnego pliku

85

Chciałbym otworzyć plik lokalny i zwrócić plik io.Reader. Powodem jest to, że muszę przesłać a io.Readerdo biblioteki, której używam, na przykład:

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

}
Xi 张 熹
źródło
1
Prawdopodobnie warto poświęcić trochę czasu na przeglądanie stron golang.org/pkg i, dla rzeczy, które robisz, os, io, io / ioutil i bufio.
twotwotwo

Odpowiedzi:

112

os.Open zwraca plik 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
źródło
30
Heh, uwielbiam tę sztuczkę pokazującą, że (* os.File) jest czytnikiem io.Reader bez możliwości otwierania plików z Playground.
twotwotwo
@twotwotwo, co dokładnie robi ten hack. Zakładam, że składniowo mówi o pliku niczego, więc nigdy nie próbuje niczego otwierać.
mschuett,
7
@mschuett Mniej więcej: jest to nilwskaźnik odpowiedniego typu, który wskazuje na plik os.File. (W tym przypadku tak naprawdę nie możesz nic przez to zrobić). A var _ io.Reader = (*os.File)(nil)przypisanie powoduje, że kompilator sprawdza, czy to *os.Filejest io.Reader(inaczej przypisanie nie byłoby prawidłowe). Jeśli przejdziesz do Playground i zmienisz *os.Filena *os.Process, zobaczysz błąd, który generuje dla rzeczy, które nie odpowiadają interfejsowi.
twotwotwo
2
@fabrizioM gdzie dokładnie w dokumentacji jest napisane, że * os.File implementuje czytnik. W przeciwnym razie, bez tej odpowiedzi, jak mógłbyś zrozumieć siebie, czytając po prostu oficjalny dokument? Ok, widzę to func (f *File) Read(b []byte) (n int, err error)samo co w Reader.
Aliaksandr Kazlou
42

Użyj os.Open () :

func Open (nazwa string) (plik * plik, błąd err)

Otwórz otwiera nazwany plik do odczytu. Jeśli się powiedzie, do odczytu można użyć metod zwróconego pliku; powiązany deskryptor pliku ma tryb O_RDONLY. Jeśli wystąpi błąd, będzie to typ * PathError.

Zwrócona wartość typu *os.Fileimplementuje io.Readerinterfejs.

ANisus
źródło
26

Typ * os.File implementuje interfejs io.Reader, więc możesz zwrócić plik jako Reader. Ale polecam skorzystać z pakietu bufio , jeśli masz zamiar czytać duże pliki, coś takiego:

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

return bufio.NewReader(file)
Yandry Pozo
źródło
4
Czy mógłbyś wyjaśnić, dlaczego polecasz bufioduże pliki?
Ciro Costa
1
@CiroCosta, jeśli masz ogromny plik Gbs, nie chcesz go odczytać w całości w pamięci, więc w takich przypadkach powinniśmy użyć bufora
Yandry Pozo
Środowisko wykonawcze go używa buforów w rozsądnych sytuacjach, np. io.Copy użyje ponownie bazowych buforów, jeśli ich interfejs jest dostępny - w przeciwnym razie utworzy bufor wewnętrzny
colm.anseo
1
Dzięki za path/file.ext. Żadna inna odpowiedź nie wyjaśniała, co os.Filebyło.
Azurespot
5

Oto przykład, w którym otwieramy plik tekstowy i tworzymy io.Reader z zwróconej instancji * os.File 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
}
spacether
źródło