1
1
package vfs
2
2
3
3
import (
4
+ "bytes"
4
5
"io"
5
6
"os"
6
7
)
@@ -24,3 +25,59 @@ func WriteFile(fs Filesystem, filename string, data []byte, perm os.FileMode) er
24
25
}
25
26
return err
26
27
}
28
+
29
+ // ReadFile reads the file named by filename and returns the contents. A
30
+ // successful call returns err == nil, not err == EOF. Because ReadFile reads
31
+ // the whole file, it does not treat an EOF from Read as an error to be
32
+ // reported.
33
+ //
34
+ // This is a port of the stdlib ioutil.ReadFile function.
35
+ func ReadFile (fs Filesystem , filename string ) ([]byte , error ) {
36
+ f , err := fs .OpenFile (filename , os .O_RDONLY , 0 )
37
+ if err != nil {
38
+ return nil , err
39
+ }
40
+ defer f .Close ()
41
+
42
+ // It's a good but not certain bet that FileInfo will tell us exactly how
43
+ // much to read, so let's try it but be prepared for the answer to be wrong.
44
+ var n int64
45
+ if fi , err := fs .Stat (filename ); err == nil {
46
+ if size := fi .Size (); size < 1e9 {
47
+ n = size
48
+ }
49
+ }
50
+
51
+ // As initial capacity for readAll, use n + a little extra in case Size is
52
+ // zero, and to avoid another allocation after Read has filled the buffer.
53
+ // The readAll call will read into its allocated internal buffer cheaply. If
54
+ // the size was wrong, we'll either waste some space off the end or
55
+ // reallocate as needed, but in the overwhelmingly common case we'll get it
56
+ // just right.
57
+ return readAll (f , n + bytes .MinRead )
58
+ }
59
+
60
+ // readAll reads from r until an error or EOF and returns the data it read from
61
+ // the internal buffer allocated with a specified capacity.
62
+ //
63
+ // This is a paste of the stdlib ioutil.readAll function.
64
+ func readAll (r io.Reader , capacity int64 ) (b []byte , err error ) {
65
+ buf := bytes .NewBuffer (make ([]byte , 0 , capacity ))
66
+
67
+ // If the buffer overflows, we will get bytes.ErrTooLarge.
68
+ // Return that as an error. Any other panic remains.
69
+ defer func () {
70
+ e := recover ()
71
+ if e == nil {
72
+ return
73
+ }
74
+ if panicErr , ok := e .(error ); ok && panicErr == bytes .ErrTooLarge {
75
+ err = panicErr
76
+ } else {
77
+ panic (e )
78
+ }
79
+ }()
80
+
81
+ _ , err = buf .ReadFrom (r )
82
+ return buf .Bytes (), err
83
+ }
0 commit comments