file.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package writer
  2. import (
  3. "IotAdmin/core/sdk/pkg"
  4. "errors"
  5. "fmt"
  6. "log"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. "time"
  11. )
  12. // timeFormat 时间格式
  13. // 用于文件名称格式
  14. const timeFormat = "2006-01-02"
  15. // FileWriter 文件写入结构体
  16. type FileWriter struct {
  17. file *os.File
  18. FilenameFunc func(*FileWriter) string
  19. num uint
  20. opts Options
  21. input chan []byte
  22. }
  23. // NewFileWriter 实例化FileWriter, 支持大文件分割
  24. func NewFileWriter(opts ...Option) (*FileWriter, error) {
  25. p := &FileWriter{
  26. opts: setDefault(),
  27. }
  28. for _, o := range opts {
  29. o(&p.opts)
  30. }
  31. if !pkg.PathExist(p.opts.path) {
  32. err := pkg.PathCreate(p.opts.path)
  33. if err != nil {
  34. log.Fatalf("[file] create dir error: %s", err.Error())
  35. }
  36. }
  37. if p.opts.timeFormat == "" {
  38. p.opts.timeFormat = timeFormat
  39. }
  40. var filename string
  41. var err error
  42. for {
  43. filename = p.getFilename()
  44. _, err := os.Stat(filename)
  45. if err != nil {
  46. if os.IsNotExist(err) {
  47. if p.num > 0 {
  48. p.num--
  49. filename = p.getFilename()
  50. }
  51. //文件不存在
  52. break
  53. }
  54. //存在,但是报错了
  55. return nil, err
  56. }
  57. p.num++
  58. if p.opts.cap == 0 {
  59. break
  60. }
  61. }
  62. p.file, err = os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
  63. if err != nil {
  64. return nil, err
  65. }
  66. p.input = make(chan []byte, 100)
  67. go p.write()
  68. return p, nil
  69. }
  70. func (p *FileWriter) write() {
  71. for {
  72. select {
  73. case d := <-p.input:
  74. _, err := p.file.Write(d)
  75. if err != nil {
  76. log.Printf("write file failed, %s\n", err.Error())
  77. }
  78. p.checkFile()
  79. }
  80. }
  81. }
  82. func (p *FileWriter) checkFile() {
  83. info, _ := p.file.Stat()
  84. if strings.Index(p.file.Name(), time.Now().Format(p.opts.timeFormat)) < 0 ||
  85. (p.opts.cap > 0 && uint(info.Size()) > p.opts.cap) {
  86. //生成新文件
  87. if uint(info.Size()) > p.opts.cap {
  88. p.num++
  89. } else {
  90. p.num = 0
  91. }
  92. filename := p.getFilename()
  93. _ = p.file.Close()
  94. p.file, _ = os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
  95. }
  96. }
  97. // Write 写入方法
  98. func (p *FileWriter) Write(data []byte) (n int, err error) {
  99. if p == nil {
  100. return 0, errors.New("logFileWriter is nil")
  101. }
  102. if p.file == nil {
  103. return 0, errors.New("file not opened")
  104. }
  105. n = len(data)
  106. go func() {
  107. p.input <- data
  108. }()
  109. return n, nil
  110. }
  111. // getFilename 获取log文件名
  112. // 目前为:以日期格式命名,eg:2006-01-02.log or 2006-01-02.log
  113. func (p *FileWriter) getFilename() string {
  114. if p.FilenameFunc != nil {
  115. return p.FilenameFunc(p)
  116. }
  117. if p.opts.cap == 0 {
  118. return filepath.Join(p.opts.path,
  119. fmt.Sprintf("%s.%s",
  120. time.Now().Format(p.opts.timeFormat),
  121. p.opts.suffix))
  122. }
  123. return filepath.Join(p.opts.path,
  124. fmt.Sprintf("%s_%d.%s",
  125. time.Now().Format(p.opts.timeFormat),
  126. p.num+1,
  127. p.opts.suffix))
  128. }