github.com/lingyao2333/mo-zero@v1.4.1/core/filex/file.go (about) 1 package filex 2 3 import ( 4 "io" 5 "os" 6 ) 7 8 const bufSize = 1024 9 10 // FirstLine returns the first line of the file. 11 func FirstLine(filename string) (string, error) { 12 file, err := os.Open(filename) 13 if err != nil { 14 return "", err 15 } 16 defer file.Close() 17 18 return firstLine(file) 19 } 20 21 // LastLine returns the last line of the file. 22 func LastLine(filename string) (string, error) { 23 file, err := os.Open(filename) 24 if err != nil { 25 return "", err 26 } 27 defer file.Close() 28 29 return lastLine(filename, file) 30 } 31 32 func firstLine(file *os.File) (string, error) { 33 var first []byte 34 var offset int64 35 for { 36 buf := make([]byte, bufSize) 37 n, err := file.ReadAt(buf, offset) 38 if err != nil && err != io.EOF { 39 return "", err 40 } 41 42 for i := 0; i < n; i++ { 43 if buf[i] == '\n' { 44 return string(append(first, buf[:i]...)), nil 45 } 46 } 47 48 first = append(first, buf[:n]...) 49 offset += bufSize 50 } 51 } 52 53 func lastLine(filename string, file *os.File) (string, error) { 54 info, err := os.Stat(filename) 55 if err != nil { 56 return "", err 57 } 58 59 var last []byte 60 offset := info.Size() 61 for { 62 offset -= bufSize 63 if offset < 0 { 64 offset = 0 65 } 66 buf := make([]byte, bufSize) 67 n, err := file.ReadAt(buf, offset) 68 if err != nil && err != io.EOF { 69 return "", err 70 } 71 72 if buf[n-1] == '\n' { 73 buf = buf[:n-1] 74 n-- 75 } else { 76 buf = buf[:n] 77 } 78 for n--; n >= 0; n-- { 79 if buf[n] == '\n' { 80 return string(append(buf[n+1:], last...)), nil 81 } 82 } 83 84 last = append(buf, last...) 85 } 86 }