github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/io/fs/readfile.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package fs 6 7 import "io" 8 9 // ReadFileFS is the interface implemented by a file system 10 // that provides an optimized implementation of ReadFile. 11 type ReadFileFS interface { 12 FS 13 14 // ReadFile reads the named file and returns its contents. 15 // A successful call returns a nil error, not io.EOF. 16 // (Because ReadFile reads the whole file, the expected EOF 17 // from the final Read is not treated as an error to be reported.) 18 ReadFile(name string) ([]byte, error) 19 } 20 21 // ReadFile reads the named file from the file system fs and returns its contents. 22 // A successful call returns a nil error, not io.EOF. 23 // (Because ReadFile reads the whole file, the expected EOF 24 // from the final Read is not treated as an error to be reported.) 25 // 26 // If fs implements ReadFileFS, ReadFile calls fs.ReadFile. 27 // Otherwise ReadFile calls fs.Open and uses Read and Close 28 // on the returned file. 29 func ReadFile(fsys FS, name string) ([]byte, error) { 30 if fsys, ok := fsys.(ReadFileFS); ok { 31 return fsys.ReadFile(name) 32 } 33 34 file, err := fsys.Open(name) 35 if err != nil { 36 return nil, err 37 } 38 defer file.Close() 39 40 var size int 41 if info, err := file.Stat(); err == nil { 42 size64 := info.Size() 43 if int64(int(size64)) == size64 { 44 size = int(size64) 45 } 46 } 47 48 data := make([]byte, 0, size+1) 49 for { 50 if len(data) >= cap(data) { 51 d := append(data[:cap(data)], 0) 52 data = d[:len(data)] 53 } 54 n, err := file.Read(data[len(data):cap(data)]) 55 data = data[:len(data)+n] 56 if err != nil { 57 if err == io.EOF { 58 err = nil 59 } 60 return data, err 61 } 62 } 63 }