github.com/3JoB/vfs@v1.0.0/ioutil.go (about) 1 package vfs 2 3 import ( 4 "bytes" 5 "io" 6 "os" 7 ) 8 9 // WriteFile writes data to a file named by filename on the given Filesystem. If 10 // the file does not exist, WriteFile creates it with permissions perm; 11 // otherwise WriteFile truncates it before writing. 12 // 13 // This is a port of the stdlib ioutil.WriteFile function. 14 func WriteFile(fs Filesystem, filename string, data []byte, perm os.FileMode) error { 15 f, err := fs.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) 16 if err != nil { 17 return err 18 } 19 n, err := f.Write(data) 20 if err == nil && n < len(data) { 21 err = io.ErrShortWrite 22 } 23 if err1 := f.Close(); err == nil { 24 err = err1 25 } 26 return err 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 }