github.com/lingyao2333/mo-zero@v1.4.1/core/iox/read.go (about) 1 package iox 2 3 import ( 4 "bufio" 5 "bytes" 6 "io" 7 "os" 8 "strings" 9 ) 10 11 type ( 12 textReadOptions struct { 13 keepSpace bool 14 withoutBlanks bool 15 omitPrefix string 16 } 17 18 // TextReadOption defines the method to customize the text reading functions. 19 TextReadOption func(*textReadOptions) 20 ) 21 22 // DupReadCloser returns two io.ReadCloser that read from the first will be written to the second. 23 // The first returned reader needs to be read first, because the content 24 // read from it will be written to the underlying buffer of the second reader. 25 func DupReadCloser(reader io.ReadCloser) (io.ReadCloser, io.ReadCloser) { 26 var buf bytes.Buffer 27 tee := io.TeeReader(reader, &buf) 28 return io.NopCloser(tee), io.NopCloser(&buf) 29 } 30 31 // KeepSpace customizes the reading functions to keep leading and tailing spaces. 32 func KeepSpace() TextReadOption { 33 return func(o *textReadOptions) { 34 o.keepSpace = true 35 } 36 } 37 38 // ReadBytes reads exactly the bytes with the length of len(buf) 39 func ReadBytes(reader io.Reader, buf []byte) error { 40 var got int 41 42 for got < len(buf) { 43 n, err := reader.Read(buf[got:]) 44 if err != nil { 45 return err 46 } 47 48 got += n 49 } 50 51 return nil 52 } 53 54 // ReadText reads content from the given file with leading and tailing spaces trimmed. 55 func ReadText(filename string) (string, error) { 56 content, err := os.ReadFile(filename) 57 if err != nil { 58 return "", err 59 } 60 61 return strings.TrimSpace(string(content)), nil 62 } 63 64 // ReadTextLines reads the text lines from given file. 65 func ReadTextLines(filename string, opts ...TextReadOption) ([]string, error) { 66 var readOpts textReadOptions 67 for _, opt := range opts { 68 opt(&readOpts) 69 } 70 71 file, err := os.Open(filename) 72 if err != nil { 73 return nil, err 74 } 75 defer file.Close() 76 77 var lines []string 78 scanner := bufio.NewScanner(file) 79 for scanner.Scan() { 80 line := scanner.Text() 81 if !readOpts.keepSpace { 82 line = strings.TrimSpace(line) 83 } 84 if readOpts.withoutBlanks && len(line) == 0 { 85 continue 86 } 87 if len(readOpts.omitPrefix) > 0 && strings.HasPrefix(line, readOpts.omitPrefix) { 88 continue 89 } 90 91 lines = append(lines, line) 92 } 93 94 return lines, scanner.Err() 95 } 96 97 // WithoutBlank customizes the reading functions to ignore blank lines. 98 func WithoutBlank() TextReadOption { 99 return func(o *textReadOptions) { 100 o.withoutBlanks = true 101 } 102 } 103 104 // OmitWithPrefix customizes the reading functions to ignore the lines with given leading prefix. 105 func OmitWithPrefix(prefix string) TextReadOption { 106 return func(o *textReadOptions) { 107 o.omitPrefix = prefix 108 } 109 }