Tạo io.Reader từ một tệp cục bộ


85

Tôi muốn mở một tệp cục bộ và trả về a io.Reader. Lý do là tôi cần cung cấp io.Readermột thư viện mà tôi đang sử dụng, như:

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

}

1
Có lẽ đáng để dành một chút thời gian duyệt qua golang.org/pkg và đối với những thứ có vẻ như bạn đang làm, hệ điều hành, io, io / ioutil và bufio.
twotwotwo

Câu trả lời:


112

os.Open trả lại một 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
Heh, thích thủ thuật cho thấy rằng (* os.File) là một io.Reader mà không thể Mở tệp từ Playground.
twotwotwo

@twotwotwo chính xác thì bản hack đó làm gì. Tôi giả định về mặt cú pháp nó nói một tệp không có gì nên nó không bao giờ cố mở bất cứ thứ gì.
mschuett

7
@mschuett Nhiều hay ít: đó là một nilcon trỏ đúng loại để trỏ đến os.File. (Trong trường hợp này, bạn thực sự không thể làm bất cứ điều gì thông qua nó.) Và var _ io.Reader = (*os.File)(nil)nhiệm vụ làm cho trình biên dịch kiểm tra xem có phải *os.Filelà một io.Reader(hoặc nếu không thì nhiệm vụ sẽ không hợp lệ). Nếu bạn đi đến Playground và thay đổi *os.Filesang, *os.Processbạn sẽ thấy lỗi mà nó tạo ra cho những thứ không đáp ứng giao diện.
twotwotwo

2
@fabrizioM nơi chính xác trong tài liệu nói rằng * os.File triển khai Trình đọc. Nếu không, nếu không có câu trả lời này, làm thế nào bạn có thể tìm ra chính mình khi chỉ đọc một tài liệu chính thức? Ok, tôi thấy điều đó func (f *File) Read(b []byte) (n int, err error), giống như trong Reader.
Aliaksandr Kazlou

42

Sử dụng os.Open () :

func Mở (chuỗi tên) (tệp * Tệp, lỗi err)

Mở sẽ mở tệp đã đặt tên để đọc. Nếu thành công, các phương thức trên tệp trả về có thể được sử dụng để đọc; bộ mô tả tệp được liên kết có chế độ O_RDONLY. Nếu có lỗi, nó sẽ có kiểu * PathError.

Giá trị trả về của kiểu *os.Filethực hiện io.Readergiao diện.


26

Kiểu * os.File triển khai giao diện io.Reader, vì vậy bạn có thể trả lại tệp dưới dạng Trình đọc. Nhưng tôi khuyên bạn nên sử dụng gói bufio nếu bạn có ý định đọc các tệp lớn, như sau:

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

return bufio.NewReader(file)

4
Bạn có thể vui lòng giải thích lý do tại sao bạn đề xuất bufiocho các tệp lớn không?
Ciro Costa

1
@CiroCosta nếu bạn có một tập tin rất lớn của GBS bạn không muốn đọc nó hoàn toàn vào bộ nhớ, vì vậy đối với những trường hợp chúng ta nên sử dụng một bộ đệm
Yandry Pozo

runtime sử dụng bộ đệm đi trong các tình huống nhạy cảm như io.Copy sẽ tái sử dụng bộ đệm cơ bản nếu giao diện của họ có sẵn - nếu không nó sẽ tạo ra một vùng đệm bên trong
colm.anseo

1
Cảm ơn vì path/file.ext. Không có câu trả lời nào khác chính xác là gì os.File.
Azurespot

5

Đây là một ví dụ mà chúng tôi mở một tệp văn bản và tạo một io.Reader từ thể hiện * os.File trả về 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
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.