read.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package iox
  2. import (
  3. "bufio"
  4. "bytes"
  5. "io"
  6. "io/ioutil"
  7. "os"
  8. "strings"
  9. )
  10. type (
  11. textReadOptions struct {
  12. keepSpace bool
  13. withoutBlanks bool
  14. omitPrefix string
  15. }
  16. TextReadOption func(*textReadOptions)
  17. )
  18. // The first returned reader needs to be read first, because the content
  19. // read from it will be written to the underlying buffer of the second reader.
  20. func DupReadCloser(reader io.ReadCloser) (io.ReadCloser, io.ReadCloser) {
  21. var buf bytes.Buffer
  22. tee := io.TeeReader(reader, &buf)
  23. return ioutil.NopCloser(tee), ioutil.NopCloser(&buf)
  24. }
  25. func KeepSpace() TextReadOption {
  26. return func(o *textReadOptions) {
  27. o.keepSpace = true
  28. }
  29. }
  30. // ReadBytes reads exactly the bytes with the length of len(buf)
  31. func ReadBytes(reader io.Reader, buf []byte) error {
  32. var got int
  33. for got < len(buf) {
  34. n, err := reader.Read(buf[got:])
  35. if err != nil {
  36. return err
  37. }
  38. got += n
  39. }
  40. return nil
  41. }
  42. func ReadText(filename string) (string, error) {
  43. content, err := ioutil.ReadFile(filename)
  44. if err != nil {
  45. return "", err
  46. }
  47. return strings.TrimSpace(string(content)), nil
  48. }
  49. func ReadTextLines(filename string, opts ...TextReadOption) ([]string, error) {
  50. var readOpts textReadOptions
  51. for _, opt := range opts {
  52. opt(&readOpts)
  53. }
  54. file, err := os.Open(filename)
  55. if err != nil {
  56. return nil, err
  57. }
  58. defer file.Close()
  59. var lines []string
  60. scanner := bufio.NewScanner(file)
  61. for scanner.Scan() {
  62. line := scanner.Text()
  63. if !readOpts.keepSpace {
  64. line = strings.TrimSpace(line)
  65. }
  66. if readOpts.withoutBlanks && len(line) == 0 {
  67. continue
  68. }
  69. if len(readOpts.omitPrefix) > 0 && strings.HasPrefix(line, readOpts.omitPrefix) {
  70. continue
  71. }
  72. lines = append(lines, line)
  73. }
  74. return lines, scanner.Err()
  75. }
  76. func WithoutBlank() TextReadOption {
  77. return func(o *textReadOptions) {
  78. o.withoutBlanks = true
  79. }
  80. }
  81. func OmitWithPrefix(prefix string) TextReadOption {
  82. return func(o *textReadOptions) {
  83. o.omitPrefix = prefix
  84. }
  85. }