-
Notifications
You must be signed in to change notification settings - Fork 1
/
watch.go
119 lines (104 loc) · 2.05 KB
/
watch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package file
import (
"bufio"
"io"
"io/ioutil"
"os"
"strings"
"github.com/fsnotify/fsnotify"
)
// Watcher 监控文件添加行
type Watcher struct {
f *os.File
r *bufio.Reader
watcher *fsnotify.Watcher
close chan bool
}
// NewWatcher 初始化一个监控程序
func NewWatcher(filename string) (w *Watcher, oldValue string, err error) {
f, err := os.OpenFile(filename, os.O_RDONLY|os.O_CREATE, os.ModePerm)
if err != nil {
return
}
// 读入原本的内容
b, err := ioutil.ReadAll(f)
if err != nil {
return
}
oldValue = string(b)
w = &Watcher{
f: f,
r: bufio.NewReader(f),
close: make(chan bool),
watcher: nil,
}
return
}
// Close 结束监控,关闭文件
func (w *Watcher) Close() {
if w.watcher != nil {
w.watcher.Close()
}
w.f.Close()
w.close <- true
}
// Watch 开始进行监控
func (w *Watcher) Watch(callback func(line string)) (err error) {
//添加要监控的对象,文件或文件夹
w.watcher, err = fsnotify.NewWatcher()
if err != nil {
return
}
err = w.watcher.Add(w.f.Name())
if err != nil {
return
}
for {
select {
case ev := <-w.watcher.Events:
if ev.Op&fsnotify.Write == fsnotify.Write {
// 监控到文件写入
for {
line, err := w.ReadLine()
if err != nil && err != io.EOF {
return err
}
if err == nil {
// 正确读入一行
go callback(line)
} else {
// 当前是由于 EOF 结束,后面无内容,不需要继续读入下一行
break
}
}
}
case err = <-w.watcher.Errors:
return
case <-w.close:
w.Close()
return nil
}
}
}
// ReadLine 读入一行的数据
func (w *Watcher) ReadLine() (line string, err error) {
pos, err := w.f.Seek(0, 1)
if err != nil {
return
}
line, err = w.r.ReadString('\n')
if err == io.EOF {
// 未读到换行符,读到 EOF
// 放弃本次读取
// 回退到原本的位置
w.f.Seek(pos, 0)
return
}
if err != nil {
// 存在其他错误
return
}
// 清楚末尾的 \n
line = strings.TrimRight(line, "\n")
return
}