Створіть io.Reader з локального файлу


85

Я хотів би відкрити локальний файл і повернути файл io.Reader. Причина полягає в тому, що мені потрібно подати файл io.Readerдо бібліотеки, якою я користуюся, наприклад:

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

}

1
Напевно, варто витратити якийсь час на перегляд golang.org/pkg, і, як би це не звучало, ви це робите, os, io, io / ioutil та bufio.
twotwotwo

Відповіді:


112

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

@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.
Олександр Казлу

42

Використовуйте os.Open () :

func Open (рядок імені) (файл * Файл, помилка помилки)

Відкрити відкриває названий файл для читання. У разі успіху для читання можна використовувати методи повернутого файлу; пов'язаний дескриптор файлу має режим O_RDONLY. Якщо є помилка, вона буде типу * PathError.

Повернене значення типу *os.Fileреалізує io.Readerінтерфейс.


26

Тип * os.File реалізує інтерфейс io.Reader, тому ви можете повернути файл як Reader. Але я рекомендую вам використовувати пакет bufio, якщо у вас є намір читати великі файли, приблизно так:

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

return bufio.NewReader(file)

4
Не могли б Ви детальніше пояснити, чому Ви рекомендуєте bufioдля великих файлів?
Сіро Коста

1
@CiroCosta, якщо у вас є величезний файл Gbs, ви не хочете читати його повністю в пам'яті, тому для цих випадків нам слід використовувати буфер
Yandry Pozo

час виконання go використовує буфери в розумних ситуаціях, наприклад, io.Copy повторно використовуватиме базові буфери, якщо доступний їх інтерфейс - інакше він створить внутрішній буфер
colm.anseo 02

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
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.