Friday, July 4, 2014

File monitoring with Golang

Fsnotify package will be merge to 1.4 or maybe someday, watch this issue:
https://code.google.com/p/go/issues/detail?id=4068

(In addition, you might like this example: github.com/noypi/filemon)

After compiling the code below, create the following files below:
files := []string{  
           "c:/temp/myprofile.txt",  
           "c:/temp/myfriends.txt",  
           "c:/temp/mydata.txt",  
      } 

Compile the code below:
 package main  
 import (  
      "fmt"  
      "io/ioutil"  
      "log"  
      "os"  
      "os/signal"  
      "path/filepath"  
      "code.google.com/p/go.exp/fsnotify"  
 )  
 type MyWatcher fsnotify.Watcher  
 func myprofile_updated(ev *fsnotify.FileEvent) {  
      fmt.Println("+myprofile_updated")  
      defer fmt.Println("-myprofile_updated")  
      if !ev.IsModify() {  
           return  
      }  
      bb, err := ioutil.ReadFile(ev.Name)  
      if nil != err {  
           // something's wrong  
           return  
      }  
      fmt.Println("new contents:", string(bb))  
 }  
 func myfriends_updated(ev *fsnotify.FileEvent) {  
      fmt.Println("+myfriends_updated")  
      defer fmt.Println("-myfriends_updated")  
 }  
 func mydata_updated(ev *fsnotify.FileEvent) {  
      fmt.Println("+mydata_updated")  
      defer fmt.Println("-mydata_updated")  
 }  
 func (this *MyWatcher) ProcessEvents() {  
      w := ((*fsnotify.Watcher)(this))  
      for {  
           select {  
           case ev := <-w.Event:  
                fname := filepath.Base(ev.Name)  
                log.Println("event:", ev, ";name:", fname)  
                switch fname {  
                case "myprofile.txt":  
                     myprofile_updated(ev)  
                case "myfriends.txt":  
                     myfriends_updated(ev)  
                case "mydata.txt":  
                     mydata_updated(ev)  
                }  
           case err := <-w.Error:  
                log.Fatalln("error:", err)  
           }  
      }  
 }  
 func (this *MyWatcher) Watch(fpath string) {  
      w := ((*fsnotify.Watcher)(this))  
      if err := w.Watch(fpath); nil != err {  
           log.Fatalln(err)  
      }  
 }  
 func main() {  
      watcher, err := fsnotify.NewWatcher()  
      if nil != err {  
           log.Fatal(err)  
      }  
      defer watcher.Close()  
      w := ((*MyWatcher)(watcher))  
      files := []string{  
           "c:/temp/myprofile.txt",  
           "c:/temp/myfriends.txt",  
           "c:/temp/mydata.txt",  
      }  
      for _, f := range files {  
           w.Watch(f)  
           defer watcher.RemoveWatch(f)  
      }  
      go w.ProcessEvents()  
      defer close(w.Error)  
      defer close(w.Event)  
      // kill event, ctrl+c  
      onkill := make(chan os.Signal, 1)  
      signal.Notify(onkill, os.Interrupt, os.Kill)  
      <-onkill // wait for event  
 }