file.go 2.9 KB

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