Issue
how can I read the last two lines from a big log file without load it into memory completely?
I need read it every 10 secs(On a Win machine)…and I’m stuck trying to read the last lines..
package main
import (
"fmt"
"time"
"os"
)
const MYFILE = "logfile.log"
func main() {
c := time.Tick(10 * time.Second)
for now := range c {
readFile(MYFILE)
}
}
func readFile(fname string){
file, err:=os.Open(fname)
if err!=nil{
panic(err)
}
buf:=make([]byte, 32)
c, err:=file.ReadAt(32, ????)
fmt.Printf("%s\n", c)
}
The log file is something like:
07/25/2013 11:55:42.400, 0.559
07/25/2013 11:55:52.200, 0.477
07/25/2013 11:56:02.000, 0.463
07/25/2013 11:56:11.800, 0.454
07/25/2013 11:56:21.600, 0.424
07/25/2013 11:56:31.400, 0.382
07/25/2013 11:56:41.200, 0.353
07/25/2013 11:56:51.000, 0.384
07/25/2013 11:57:00.800, 0.393
07/25/2013 11:57:10.600, 0.456
Thanks!
Solution
You can use file.Seek() or file.ReadAt() to almost the end and then Reading forward. You can only estimate where to start seeking unless you can know that 2 lines = x bytes.
You can get the File length by using the os.Stat(name)
Here is an example based on ReadAt, Stat, and your sample log file:
package main
import (
"fmt"
"os"
"time"
)
const MYFILE = "logfile.log"
func main() {
c := time.Tick(10 * time.Second)
for _ = range c {
readFile(MYFILE)
}
}
func readFile(fname string) {
file, err := os.Open(fname)
if err != nil {
panic(err)
}
defer file.Close()
buf := make([]byte, 62)
stat, err := os.Stat(fname)
start := stat.Size() - 62
_, err = file.ReadAt(buf, start)
if err == nil {
fmt.Printf("%s\n", buf)
}
}
Answered By – Joshua
Answer Checked By – Willingham (GoLangFix Volunteer)