github.com/gogf/gf@v1.16.9/os/gfile/gfile_contents.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gfile 8 9 import ( 10 "bufio" 11 "io" 12 "io/ioutil" 13 "os" 14 ) 15 16 var ( 17 // DefaultReadBuffer is the buffer size for reading file content. 18 DefaultReadBuffer = 1024 19 ) 20 21 // GetContents returns the file content of <path> as string. 22 // It returns en empty string if it fails reading. 23 func GetContents(path string) string { 24 return string(GetBytes(path)) 25 } 26 27 // GetBytes returns the file content of <path> as []byte. 28 // It returns nil if it fails reading. 29 func GetBytes(path string) []byte { 30 data, err := ioutil.ReadFile(path) 31 if err != nil { 32 return nil 33 } 34 return data 35 } 36 37 // putContents puts binary content to file of <path>. 38 func putContents(path string, data []byte, flag int, perm os.FileMode) error { 39 // It supports creating file of <path> recursively. 40 dir := Dir(path) 41 if !Exists(dir) { 42 if err := Mkdir(dir); err != nil { 43 return err 44 } 45 } 46 // Opening file with given <flag> and <perm>. 47 f, err := OpenWithFlagPerm(path, flag, perm) 48 if err != nil { 49 return err 50 } 51 defer f.Close() 52 if n, err := f.Write(data); err != nil { 53 return err 54 } else if n < len(data) { 55 return io.ErrShortWrite 56 } 57 return nil 58 } 59 60 // Truncate truncates file of <path> to given size by <size>. 61 func Truncate(path string, size int) error { 62 return os.Truncate(path, int64(size)) 63 } 64 65 // PutContents puts string <content> to file of <path>. 66 // It creates file of <path> recursively if it does not exist. 67 func PutContents(path string, content string) error { 68 return putContents(path, []byte(content), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, DefaultPermOpen) 69 } 70 71 // PutContentsAppend appends string <content> to file of <path>. 72 // It creates file of <path> recursively if it does not exist. 73 func PutContentsAppend(path string, content string) error { 74 return putContents(path, []byte(content), os.O_WRONLY|os.O_CREATE|os.O_APPEND, DefaultPermOpen) 75 } 76 77 // PutBytes puts binary <content> to file of <path>. 78 // It creates file of <path> recursively if it does not exist. 79 func PutBytes(path string, content []byte) error { 80 return putContents(path, content, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, DefaultPermOpen) 81 } 82 83 // PutBytesAppend appends binary <content> to file of <path>. 84 // It creates file of <path> recursively if it does not exist. 85 func PutBytesAppend(path string, content []byte) error { 86 return putContents(path, content, os.O_WRONLY|os.O_CREATE|os.O_APPEND, DefaultPermOpen) 87 } 88 89 // GetNextCharOffset returns the file offset for given <char> starting from <start>. 90 func GetNextCharOffset(reader io.ReaderAt, char byte, start int64) int64 { 91 buffer := make([]byte, DefaultReadBuffer) 92 offset := start 93 for { 94 if n, err := reader.ReadAt(buffer, offset); n > 0 { 95 for i := 0; i < n; i++ { 96 if buffer[i] == char { 97 return int64(i) + offset 98 } 99 } 100 offset += int64(n) 101 } else if err != nil { 102 break 103 } 104 } 105 return -1 106 } 107 108 // GetNextCharOffsetByPath returns the file offset for given <char> starting from <start>. 109 // It opens file of <path> for reading with os.O_RDONLY flag and default perm. 110 func GetNextCharOffsetByPath(path string, char byte, start int64) int64 { 111 if f, err := OpenWithFlagPerm(path, os.O_RDONLY, DefaultPermOpen); err == nil { 112 defer f.Close() 113 return GetNextCharOffset(f, char, start) 114 } 115 return -1 116 } 117 118 // GetBytesTilChar returns the contents of the file as []byte 119 // until the next specified byte <char> position. 120 // 121 // Note: Returned value contains the character of the last position. 122 func GetBytesTilChar(reader io.ReaderAt, char byte, start int64) ([]byte, int64) { 123 if offset := GetNextCharOffset(reader, char, start); offset != -1 { 124 return GetBytesByTwoOffsets(reader, start, offset+1), offset 125 } 126 return nil, -1 127 } 128 129 // GetBytesTilCharByPath returns the contents of the file given by <path> as []byte 130 // until the next specified byte <char> position. 131 // It opens file of <path> for reading with os.O_RDONLY flag and default perm. 132 // 133 // Note: Returned value contains the character of the last position. 134 func GetBytesTilCharByPath(path string, char byte, start int64) ([]byte, int64) { 135 if f, err := OpenWithFlagPerm(path, os.O_RDONLY, DefaultPermOpen); err == nil { 136 defer f.Close() 137 return GetBytesTilChar(f, char, start) 138 } 139 return nil, -1 140 } 141 142 // GetBytesByTwoOffsets returns the binary content as []byte from <start> to <end>. 143 // Note: Returned value does not contain the character of the last position, which means 144 // it returns content range as [start, end). 145 func GetBytesByTwoOffsets(reader io.ReaderAt, start int64, end int64) []byte { 146 buffer := make([]byte, end-start) 147 if _, err := reader.ReadAt(buffer, start); err != nil { 148 return nil 149 } 150 return buffer 151 } 152 153 // GetBytesByTwoOffsetsByPath returns the binary content as []byte from <start> to <end>. 154 // Note: Returned value does not contain the character of the last position, which means 155 // it returns content range as [start, end). 156 // It opens file of <path> for reading with os.O_RDONLY flag and default perm. 157 func GetBytesByTwoOffsetsByPath(path string, start int64, end int64) []byte { 158 if f, err := OpenWithFlagPerm(path, os.O_RDONLY, DefaultPermOpen); err == nil { 159 defer f.Close() 160 return GetBytesByTwoOffsets(f, start, end) 161 } 162 return nil 163 } 164 165 // ReadLines reads file content line by line, which is passed to the callback function <callback> as string. 166 // It matches each line of text, separated by chars '\r' or '\n', stripped any trailing end-of-line marker. 167 // 168 // Note that the parameter passed to callback function might be an empty value, and the last non-empty line 169 // will be passed to callback function <callback> even if it has no newline marker. 170 func ReadLines(file string, callback func(text string) error) error { 171 f, err := os.Open(file) 172 if err != nil { 173 return err 174 } 175 defer f.Close() 176 177 scanner := bufio.NewScanner(f) 178 for scanner.Scan() { 179 if err = callback(scanner.Text()); err != nil { 180 return err 181 } 182 } 183 return nil 184 } 185 186 // ReadByteLines reads file content line by line, which is passed to the callback function <callback> as []byte. 187 // It matches each line of text, separated by chars '\r' or '\n', stripped any trailing end-of-line marker. 188 // 189 // Note that the parameter passed to callback function might be an empty value, and the last non-empty line 190 // will be passed to callback function <callback> even if it has no newline marker. 191 // 192 // Deprecated, use ReadLinesBytes instead. 193 func ReadByteLines(file string, callback func(bytes []byte) error) error { 194 return ReadLinesBytes(file, callback) 195 } 196 197 // ReadLinesBytes reads file content line by line, which is passed to the callback function <callback> as []byte. 198 // It matches each line of text, separated by chars '\r' or '\n', stripped any trailing end-of-line marker. 199 // 200 // Note that the parameter passed to callback function might be an empty value, and the last non-empty line 201 // will be passed to callback function <callback> even if it has no newline marker. 202 func ReadLinesBytes(file string, callback func(bytes []byte) error) error { 203 f, err := os.Open(file) 204 if err != nil { 205 return err 206 } 207 defer f.Close() 208 209 scanner := bufio.NewScanner(f) 210 for scanner.Scan() { 211 if err = callback(scanner.Bytes()); err != nil { 212 return err 213 } 214 } 215 return nil 216 }