]>
Commit | Line | Data |
---|---|---|
7a938933 ILT |
1 | // Copyright 2009 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 | ||
9ff56c95 | 5 | // Package ioutil implements some I/O utility functions. |
7a938933 ILT |
6 | package ioutil |
7 | ||
8 | import ( | |
9 | "bytes" | |
10 | "io" | |
11 | "os" | |
12 | "sort" | |
bae90c98 | 13 | "sync" |
7a938933 ILT |
14 | ) |
15 | ||
8039ca76 ILT |
16 | // readAll reads from r until an error or EOF and returns the data it read |
17 | // from the internal buffer allocated with a specified capacity. | |
9af4cb95 | 18 | func readAll(r io.Reader, capacity int64) (b []byte, err error) { |
8039ca76 | 19 | buf := bytes.NewBuffer(make([]byte, 0, capacity)) |
9af4cb95 ILT |
20 | // If the buffer overflows, we will get bytes.ErrTooLarge. |
21 | // Return that as an error. Any other panic remains. | |
22 | defer func() { | |
23 | e := recover() | |
24 | if e == nil { | |
25 | return | |
26 | } | |
27 | if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge { | |
28 | err = panicErr | |
29 | } else { | |
30 | panic(e) | |
31 | } | |
32 | }() | |
33 | _, err = buf.ReadFrom(r) | |
8039ca76 ILT |
34 | return buf.Bytes(), err |
35 | } | |
36 | ||
7a938933 | 37 | // ReadAll reads from r until an error or EOF and returns the data it read. |
94252f4b ILT |
38 | // A successful call returns err == nil, not err == EOF. Because ReadAll is |
39 | // defined to read from src until EOF, it does not treat an EOF from Read | |
40 | // as an error to be reported. | |
2fd401c8 | 41 | func ReadAll(r io.Reader) ([]byte, error) { |
8039ca76 | 42 | return readAll(r, bytes.MinRead) |
7a938933 ILT |
43 | } |
44 | ||
45 | // ReadFile reads the file named by filename and returns the contents. | |
94252f4b ILT |
46 | // A successful call returns err == nil, not err == EOF. Because ReadFile |
47 | // reads the whole file, it does not treat an EOF from Read as an error | |
48 | // to be reported. | |
2fd401c8 | 49 | func ReadFile(filename string) ([]byte, error) { |
405ca104 | 50 | f, err := os.Open(filename) |
7a938933 ILT |
51 | if err != nil { |
52 | return nil, err | |
53 | } | |
54 | defer f.Close() | |
55 | // It's a good but not certain bet that FileInfo will tell us exactly how much to | |
56 | // read, so let's try it but be prepared for the answer to be wrong. | |
7a938933 | 57 | var n int64 |
9a18821c ILT |
58 | |
59 | if fi, err := f.Stat(); err == nil { | |
60 | // Don't preallocate a huge buffer, just in case. | |
61 | if size := fi.Size(); size < 1e9 { | |
62 | n = size | |
63 | } | |
7a938933 | 64 | } |
8039ca76 ILT |
65 | // As initial capacity for readAll, use n + a little extra in case Size is zero, |
66 | // and to avoid another allocation after Read has filled the buffer. The readAll | |
67 | // call will read into its allocated internal buffer cheaply. If the size was | |
68 | // wrong, we'll either waste some space off the end or reallocate as needed, but | |
7a938933 | 69 | // in the overwhelmingly common case we'll get it just right. |
8039ca76 | 70 | return readAll(f, n+bytes.MinRead) |
7a938933 ILT |
71 | } |
72 | ||
73 | // WriteFile writes data to a file named by filename. | |
74 | // If the file does not exist, WriteFile creates it with permissions perm; | |
75 | // otherwise WriteFile truncates it before writing. | |
af92e385 | 76 | func WriteFile(filename string, data []byte, perm os.FileMode) error { |
405ca104 | 77 | f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) |
7a938933 ILT |
78 | if err != nil { |
79 | return err | |
80 | } | |
81 | n, err := f.Write(data) | |
7a938933 ILT |
82 | if err == nil && n < len(data) { |
83 | err = io.ErrShortWrite | |
84 | } | |
f038dae6 ILT |
85 | if err1 := f.Close(); err == nil { |
86 | err = err1 | |
87 | } | |
7a938933 ILT |
88 | return err |
89 | } | |
90 | ||
7b1c3dd9 ILT |
91 | // byName implements sort.Interface. |
92 | type byName []os.FileInfo | |
7a938933 | 93 | |
7b1c3dd9 ILT |
94 | func (f byName) Len() int { return len(f) } |
95 | func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() } | |
96 | func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] } | |
7a938933 ILT |
97 | |
98 | // ReadDir reads the directory named by dirname and returns | |
99 | // a list of sorted directory entries. | |
7b1c3dd9 | 100 | func ReadDir(dirname string) ([]os.FileInfo, error) { |
405ca104 | 101 | f, err := os.Open(dirname) |
7a938933 ILT |
102 | if err != nil { |
103 | return nil, err | |
104 | } | |
105 | list, err := f.Readdir(-1) | |
106 | f.Close() | |
107 | if err != nil { | |
108 | return nil, err | |
109 | } | |
7b1c3dd9 ILT |
110 | sort.Sort(byName(list)) |
111 | return list, nil | |
7a938933 | 112 | } |
8039ca76 ILT |
113 | |
114 | type nopCloser struct { | |
115 | io.Reader | |
116 | } | |
117 | ||
2fd401c8 | 118 | func (nopCloser) Close() error { return nil } |
8039ca76 ILT |
119 | |
120 | // NopCloser returns a ReadCloser with a no-op Close method wrapping | |
121 | // the provided Reader r. | |
122 | func NopCloser(r io.Reader) io.ReadCloser { | |
123 | return nopCloser{r} | |
124 | } | |
9ff56c95 ILT |
125 | |
126 | type devNull int | |
127 | ||
d8f41257 ILT |
128 | // devNull implements ReaderFrom as an optimization so io.Copy to |
129 | // ioutil.Discard can avoid doing unnecessary work. | |
130 | var _ io.ReaderFrom = devNull(0) | |
131 | ||
2fd401c8 | 132 | func (devNull) Write(p []byte) (int, error) { |
9ff56c95 ILT |
133 | return len(p), nil |
134 | } | |
135 | ||
f038dae6 ILT |
136 | func (devNull) WriteString(s string) (int, error) { |
137 | return len(s), nil | |
138 | } | |
139 | ||
bae90c98 ILT |
140 | var blackHolePool = sync.Pool{ |
141 | New: func() interface{} { | |
142 | b := make([]byte, 8192) | |
143 | return &b | |
144 | }, | |
145 | } | |
146 | ||
2fd401c8 | 147 | func (devNull) ReadFrom(r io.Reader) (n int64, err error) { |
bae90c98 | 148 | bufp := blackHolePool.Get().(*[]byte) |
adb0401d ILT |
149 | readSize := 0 |
150 | for { | |
bae90c98 | 151 | readSize, err = r.Read(*bufp) |
adb0401d ILT |
152 | n += int64(readSize) |
153 | if err != nil { | |
bae90c98 | 154 | blackHolePool.Put(bufp) |
2fd401c8 | 155 | if err == io.EOF { |
adb0401d ILT |
156 | return n, nil |
157 | } | |
158 | return | |
159 | } | |
160 | } | |
adb0401d ILT |
161 | } |
162 | ||
9ff56c95 ILT |
163 | // Discard is an io.Writer on which all Write calls succeed |
164 | // without doing anything. | |
165 | var Discard io.Writer = devNull(0) |