github.com/kaydxh/golang@v0.0.131/go/io/io.go (about) 1 /* 2 *Copyright (c) 2022, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package io 23 24 import ( 25 "bufio" 26 "bytes" 27 "io" 28 "io/ioutil" 29 "os" 30 31 os_ "github.com/kaydxh/golang/go/os" 32 ) 33 34 // ReadFileLines read line from file divide with \n 35 func ReadFileLines(filepath string) ([]string, error) { 36 file, err := os_.OpenAll(filepath, os.O_RDONLY, 0) 37 if err != nil { 38 return nil, err 39 } 40 defer file.Close() 41 42 var lines []string 43 scanner := bufio.NewScanner(file) 44 scanner.Split(bufio.ScanLines) 45 for scanner.Scan() { 46 lines = append(lines, scanner.Text()) 47 } 48 49 return lines, nil 50 } 51 52 // ReadLines read line from byteArray divide with \n 53 func ReadLines(byteArray []byte) []string { 54 var lines []string 55 index := 0 56 readIndex := 0 57 for ; readIndex < len(byteArray); index++ { 58 line, n := ReadLineAt(readIndex, byteArray) 59 readIndex = n 60 61 lines = append(lines, string(line)) 62 } 63 64 return lines 65 } 66 67 func ReadLineAt(readIndex int, byteArray []byte) ([]byte, int) { 68 currentReadIndex := readIndex 69 70 // consume left spaces 71 for currentReadIndex < len(byteArray) { 72 if byteArray[currentReadIndex] == ' ' { 73 currentReadIndex++ 74 } else { 75 break 76 } 77 } 78 79 // leftTrimIndex stores the left index of the line after the line is left-trimmed 80 leftTrimIndex := currentReadIndex 81 82 // rightTrimIndex stores the right index of the line after the line is right-trimmed 83 // it is set to -1 since the correct value has not yet been determined. 84 rightTrimIndex := -1 85 86 for ; currentReadIndex < len(byteArray); currentReadIndex++ { 87 if byteArray[currentReadIndex] == ' ' { 88 // set rightTrimIndex 89 if rightTrimIndex == -1 { 90 rightTrimIndex = currentReadIndex 91 } 92 } else if (byteArray[currentReadIndex] == '\n') || (currentReadIndex == (len(byteArray) - 1)) { 93 // end of line or byte buffer is reached 94 if currentReadIndex <= leftTrimIndex { 95 return nil, currentReadIndex + 1 96 } 97 // set the rightTrimIndex 98 if rightTrimIndex == -1 { 99 rightTrimIndex = currentReadIndex 100 if currentReadIndex == (len(byteArray)-1) && (byteArray[currentReadIndex] != '\n') { 101 // ensure that the last character is part of the returned string, 102 // unless the last character is '\n' 103 rightTrimIndex = currentReadIndex + 1 104 } 105 } 106 // Avoid unnecessary allocation. 107 return byteArray[leftTrimIndex:rightTrimIndex], currentReadIndex + 1 108 } else { 109 // unset rightTrimIndex 110 rightTrimIndex = -1 111 } 112 } 113 114 return nil, currentReadIndex 115 } 116 117 //ReadFile read data from file 118 func ReadFile(filePath string) ([]byte, error) { 119 data, err := ioutil.ReadFile(filePath) 120 if err != nil { 121 return nil, err 122 } 123 124 return data, err 125 } 126 127 func WriteFile(filePath string, content []byte, appended bool) error { 128 file, err := os_.OpenFile(filePath, appended) 129 if err != nil { 130 return err 131 } 132 defer file.Close() 133 134 buf := bufio.NewWriter(file) 135 _, err = buf.Write(content) 136 if err != nil { 137 return err 138 } 139 140 if err := buf.Flush(); err != nil { 141 return err 142 } 143 144 return nil 145 } 146 147 // WriteLine join all line to file. 148 func WriteFileLines(filePath string, lines []string, appended bool) (err error) { 149 150 file, err := os_.OpenFile(filePath, appended) 151 if err != nil { 152 return err 153 } 154 defer file.Close() 155 156 buf := bufio.NewWriter(file) 157 for i := range lines { 158 if _, err = buf.WriteString(lines[i] + "\n"); err != nil { 159 return err 160 } 161 } 162 163 if err := buf.Flush(); err != nil { 164 return err 165 } 166 167 return nil 168 } 169 170 // WriteLine join all words with spaces, terminate with newline and 171 // write to file. 172 func WriteFileLine(filePath string, words []string, appended bool) (err error) { 173 file, err := os_.OpenFile(filePath, appended) 174 if err != nil { 175 return err 176 } 177 defer file.Close() 178 179 buf := bytes.NewBuffer(nil) 180 err = WriteLine(buf, words...) 181 if err != nil { 182 return err 183 } 184 _, err = file.Write(buf.Bytes()) 185 if err != nil { 186 return err 187 } 188 189 return nil 190 } 191 192 // WriteLine join all words with spaces, terminate with newline and write to buff. 193 func WriteLine(buf *bytes.Buffer, words ...string) error { 194 // We avoid strings.Join for performance reasons. 195 for i := range words { 196 _, err := buf.WriteString(words[i]) 197 if err != nil { 198 return err 199 } 200 if i < len(words)-1 { 201 err = buf.WriteByte(' ') 202 } else { 203 err = buf.WriteByte('\n') 204 } 205 if err != nil { 206 return err 207 } 208 209 } 210 211 return nil 212 } 213 214 // WriteBytesLine write bytes to buffer, terminate with newline 215 func WriteBytesLine(buf *bytes.Buffer, bytes []byte) error { 216 _, err := buf.Write(bytes) 217 if err != nil { 218 return err 219 } 220 221 err = buf.WriteByte('\n') 222 if err != nil { 223 return err 224 } 225 226 return nil 227 } 228 229 func WriteBytesAt(filepath string, bytes []byte, offset int64) error { 230 file, err := os_.OpenAll(filepath, os.O_CREATE|os.O_RDWR, os.ModePerm) 231 if err != nil { 232 return err 233 } 234 defer file.Close() 235 236 n, err := file.Seek(offset, io.SeekStart) 237 if err != nil { 238 return err 239 } 240 _, err = file.WriteAt(bytes, n) 241 if err != nil { 242 return err 243 } 244 245 return nil 246 } 247 248 func WriteReader(filepath string, r io.Reader) error { 249 file, err := os_.OpenAll(filepath, os.O_CREATE|os.O_RDWR, os.ModePerm) 250 // file, err := os_.OpenFile(filepath, true) 251 if err != nil { 252 return err 253 } 254 defer file.Close() 255 256 _, err = io.Copy(file, r) 257 return err 258 } 259 260 func WriteReaderAt(filepath string, r io.Reader, offset, length int64) error { 261 file, err := os_.OpenAll(filepath, os.O_CREATE|os.O_RDWR, os.ModePerm) 262 // file, err := os_.OpenFile(filepath, true) 263 if err != nil { 264 return err 265 } 266 defer file.Close() 267 268 buf := make([]byte, 1024) 269 var total int64 270 271 for total < length { 272 nr, err := r.Read(buf) 273 if err == nil || err == io.EOF { 274 if nr > 0 { 275 n, err := file.Seek(offset, io.SeekStart) 276 if err != nil { 277 return err 278 } 279 _, err = file.WriteAt(buf[:nr], n) 280 if err != nil { 281 return err 282 } 283 284 offset += int64(nr) 285 total += int64(nr) 286 } 287 288 if err == io.EOF { 289 break 290 } 291 292 } else { 293 return err 294 } 295 296 } 297 298 return nil 299 }