Создайте io.Reader из локального файла

89

Я хотел бы открыть локальный файл и вернуть io.Reader. Причина в том, что мне нужно передать a io.Readerв библиотеку, которую я использую, например:

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

}
Си 张 熹
источник
1
Наверное, стоит потратить некоторое время на просмотр golang.org/pkg и, если вам кажется, что вы делаете, os, io, io / ioutil и bufio.
twotwotwo 05

Ответы:

117

os.Open возвращает 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")
}
фабрициоМ
источник
30
Хех, мне нравится трюк, показывающий, что (* os.File) является io.Reader без возможности открывать файлы с игровой площадки.
twotwotwo 05
@twotwotwo, что именно делает этот хак? Я предполагаю, что синтаксически он говорит о пустом файле, поэтому никогда не пытается что-либо открыть.
mschuett
7
@mschuett Более или менее: это nilуказатель правильного типа, указывающий на os.File. (В этом случае вы действительно ничего не можете сделать через него.) И var _ io.Reader = (*os.File)(nil)назначение заставляет компилятор проверять, что *os.Fileэто io.Reader(иначе присвоение было бы недействительным). Если вы перейдете на площадку и переключитесь *os.Fileна, *os.Processвы увидите ошибку, которую он генерирует для вещей, которые не соответствуют интерфейсу.
twotwotwo
2
@fabrizioM, где именно в документации сказано, что * os.File реализует Reader. Иначе, без этого ответа, как бы вы могли понять себя, просто прочитав официальный документ? Хорошо, я вижу func (f *File) Read(b []byte) (n int, err error), как в Reader.
Александр Казлов
43

Используйте os.Open () :

func Open (строка имени) (файл * файл, ошибка ошибки)

Открыть открывает указанный файл для чтения. В случае успеха методы возвращенного файла можно использовать для чтения; связанный дескриптор файла имеет режим O_RDONLY. Если есть ошибка, она будет типа * PathError.

Возвращаемое значение типа *os.Fileреализует io.Readerинтерфейс.

Анисус
источник
27

Тип * os.File реализует интерфейс io.Reader, поэтому вы можете вернуть файл как Reader. Но я рекомендую вам использовать пакет bufio , если вы собираетесь читать большие файлы, примерно так:

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

return bufio.NewReader(file)
Яндри Позо
источник
4
Не могли бы вы пояснить, почему вы рекомендуете bufioдля больших файлов?
Чиро Коста
1
@CiroCosta, если у вас есть огромный файл в Гб, вы не хотите полностью читать его в памяти, поэтому для таких случаев мы должны использовать буфер
Яндри Посо
среда выполнения go использует буферы в разумных ситуациях, например, io.Copy будет повторно использовать нижележащие буферы, если их интерфейс доступен - в противном случае он создаст внутренний буфер
colm.anseo
1
Спасибо за path/file.ext. Никакой другой ответ не объяснял, что os.Fileбыло.
Azurespot
5

Вот пример, в котором мы открываем текстовый файл и создаем io.Reader из возвращенного экземпляра * 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
}
космический корабль
источник