reader.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package file
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "os"
  7. )
  8. var (
  9. buffSize = 1 << 20
  10. )
  11. // ReadLineFromEnd --
  12. type ReadLineFromEnd struct {
  13. f *os.File
  14. fileSize int
  15. bwr *bytes.Buffer
  16. lineBuff []byte
  17. swapBuff []byte
  18. isFirst bool
  19. }
  20. // NewReadLineFromEnd --
  21. func NewReadLineFromEnd(name string) (rd *ReadLineFromEnd, err error) {
  22. f, err := os.Open(name)
  23. if err != nil {
  24. return nil, err
  25. }
  26. info, err := f.Stat()
  27. if info.IsDir() {
  28. return nil, fmt.Errorf("not file")
  29. }
  30. fileSize := int(info.Size())
  31. rd = &ReadLineFromEnd{
  32. f: f,
  33. fileSize: fileSize,
  34. bwr: bytes.NewBuffer([]byte{}),
  35. lineBuff: make([]byte, 0),
  36. swapBuff: make([]byte, buffSize),
  37. isFirst: true,
  38. }
  39. return rd, nil
  40. }
  41. // ReadLine 结尾包含'\n'
  42. func (c *ReadLineFromEnd) ReadLine() (line []byte, err error) {
  43. var ok bool
  44. for {
  45. ok, err = c.buff()
  46. if err != nil {
  47. return nil, err
  48. }
  49. if ok {
  50. break
  51. }
  52. }
  53. line, err = c.bwr.ReadBytes('\n')
  54. if err == io.EOF && c.fileSize > 0 {
  55. err = nil
  56. }
  57. return line, err
  58. }
  59. // Close --
  60. func (c *ReadLineFromEnd) Close() (err error) {
  61. return c.f.Close()
  62. }
  63. func (c *ReadLineFromEnd) buff() (ok bool, err error) {
  64. if c.fileSize == 0 {
  65. return true, nil
  66. }
  67. if c.bwr.Len() >= buffSize {
  68. return true, nil
  69. }
  70. offset := 0
  71. if c.fileSize > buffSize {
  72. offset = c.fileSize - buffSize
  73. }
  74. _, err = c.f.Seek(int64(offset), 0)
  75. if err != nil {
  76. return false, err
  77. }
  78. n, err := c.f.Read(c.swapBuff)
  79. if err != nil && err != io.EOF {
  80. return false, err
  81. }
  82. if c.fileSize < n {
  83. n = c.fileSize
  84. }
  85. if n == 0 {
  86. return true, nil
  87. }
  88. for {
  89. m := bytes.LastIndex(c.swapBuff[:n], []byte{'\n'})
  90. if m == -1 {
  91. break
  92. }
  93. if m < n-1 {
  94. err = c.writeLine(c.swapBuff[m+1 : n])
  95. if err != nil {
  96. return false, err
  97. }
  98. ok = true
  99. } else if m == n-1 && !c.isFirst {
  100. err = c.writeLine(nil)
  101. if err != nil {
  102. return false, err
  103. }
  104. ok = true
  105. }
  106. n = m
  107. if n == 0 {
  108. break
  109. }
  110. }
  111. if n > 0 {
  112. reverseBytes(c.swapBuff[:n])
  113. c.lineBuff = append(c.lineBuff, c.swapBuff[:n]...)
  114. }
  115. if offset == 0 {
  116. err = c.writeLine(nil)
  117. if err != nil {
  118. return false, err
  119. }
  120. ok = true
  121. }
  122. c.fileSize = offset
  123. if c.isFirst {
  124. c.isFirst = false
  125. }
  126. return ok, nil
  127. }
  128. func (c *ReadLineFromEnd) writeLine(b []byte) (err error) {
  129. if len(b) > 0 {
  130. _, err = c.bwr.Write(b)
  131. if err != nil {
  132. return err
  133. }
  134. }
  135. if len(c.lineBuff) > 0 {
  136. reverseBytes(c.lineBuff)
  137. _, err = c.bwr.Write(c.lineBuff)
  138. if err != nil {
  139. return err
  140. }
  141. c.lineBuff = c.lineBuff[:0]
  142. }
  143. _, err = c.bwr.Write([]byte{'\n'})
  144. if err != nil {
  145. return err
  146. }
  147. return nil
  148. }
  149. func reverseBytes(b []byte) {
  150. n := len(b)
  151. if n <= 1 {
  152. return
  153. }
  154. for i := 0; i < n; i++ {
  155. k := n - 1
  156. if k != i {
  157. b[i], b[k] = b[k], b[i]
  158. }
  159. n--
  160. }
  161. }