我如何从一个大的日志文件中读取最后两行而不将其完全加载到内存中?
我需要每10秒读一次(在赢的机器上).
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)
}
日志文件类似于:
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
谢谢你,谢谢
6条答案
按热度按时间gcuhipw91#
您可以使用file.seek()或file.ReadAt()直到几乎结束,然后阅读前进。你只能估计从哪里开始寻找,除非你知道2行= x字节。
您可以使用func(*File)Stat获取文件长度
下面是一个基于ReadAt、Stat和示例日志文件的示例:
djmepvbi2#
有些人会来到这个页面,寻找有效的阅读日志文件的最后一行(如tail命令行工具)。
这是我的版本,读取一个大文件的最后一行。它使用了前面的两个建议(使用Seek和File Stat)。
它逐字节反向读取文件(无需设置缓冲区大小),直到找到行的开头或文件的开头。
vlurs2pr3#
我认为
File.Seek(0, 2)
和File.Read()
的组合应该可以工作。Seek
调用会将您带到文件的末尾。你可以Seek
到一个位置之前的一点,以获得最后几行。然后你Read
,直到你的goroutine睡眠10秒;下一个Read
有机会给你更多的数据。您可以从GNU
tail
's source中获得这个想法(以及最初显示最后几行的回扫描逻辑)。qyuhtwio4#
好吧,这只是一个原始的想法,也许不是最好的方法,你应该检查和改进它,但似乎工作.
我希望有经验的Go用户也能做出贡献。
使用Stat,您可以获取文件的大小,并从中获取用于ReadAt的偏移量
au9on6nz5#
我使用
tail
来减少占用空间。不知道它是如何比较明智的表现。对于Windows,你必须这样做
kqqjbcuj6#
下面是我写的以逆序方式阅读大字节的代码。它不会在尾随空格处中断。
这段代码所做的是反向循环字节,它计算遇到的字节数。当它检测到一个换行符时,它通过该数字循环回去,将该行和
append()
写入结果[]byte
,然后重置数字。直到maxLine
变量被满足。这太复杂了,如果你只是想从特定的行中读取字节,可能有更好的方法。变量名一直渴望更容易阅读。
https://go.dev/play/p/qKDFxiJQAfF