我试图使用bufio.NewScanner
逐行读取文件,使用以下函数。
func TailFromStart(fd *os.File, wg *sync.WaitGroup) {
fd.Seek(0,0)
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
line := scanner.Text()
offset, _ := fd.Seek(0, 1)
fmt.Println(offset)
fmt.Println(line)
offsetreset, _ := fd.Seek(offset, 0)
fmt.Println(offsetreset)
}
offset, err := fd.Seek(0, 1)
CheckError(err)
fmt.Println(offset)
wg.Done()
}
我希望它按递增顺序打印偏移量,但是,它会在每次迭代中打印相同的值,直到文件达到EOF
。
127.0.0.1 - - [11/Aug/2016:22:10:39 +0530] "GET /ttt HTTP/1.1" 404 437 "-" "curl/7.38.0"
613
613
127.0.0.1 - - [11/Aug/2016:22:10:42 +0530] "GET /qqq HTTP/1.1" 404 437 "-" "curl/7.38.0"
613
613是文件中的总字符数。
cat /var/log/apache2/access.log | wc
7 84 613
我是否理解错误,或者bufio.NewScanner
是否在内存中读取整个文件,并在内存中进行迭代?如果是这样,有没有更好的方法逐行阅读?
答案 0 :(得分:4)
请参阅func (s *Scanner) Buffer(buf []byte, max int)
文档:
缓冲区设置扫描时使用的初始缓冲区和最大值 扫描期间可能分配的缓冲区大小。最大值 令牌大小是max和
cap(buf)
中的较大者 如果是max <= cap(buf)
, 扫描仅使用此缓冲区,不进行分配。默认情况下,Scan使用内部缓冲区并设置最大令牌 大小为
MaxScanTokenSize
。如果在扫描开始后调用它,则缓冲区会发生混乱。
和
MaxScanTokenSize是用于缓冲令牌的最大大小,除非 用户使用Scan.Buffer提供显式缓冲区。实际上 最大令牌大小可能会更小,因为缓冲区可能需要包括, 例如,换行符。
MaxScanTokenSize = 64 * 1024 startBufSize = 4096 // Size of initial allocation for buffer.
不,因为@JimB说它只读取缓冲区大小,请参阅此测试样本:
对于小于4096字节,它将所有文件内容读入缓冲区,
但对于大文件,只读取4096字节,
尝试使用大文件:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
fd, err := os.Open("big.txt")
if err != nil {
panic(err)
}
defer fd.Close()
n, err := fd.Seek(0, 0)
if err != nil {
panic(err)
}
fmt.Println("n =", n) // 0
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
fmt.Println(scanner.Text())
break
}
offset, err := fd.Seek(0, 1)
if err != nil {
panic(err)
}
fmt.Println("offset =", offset) //4096
offsetreset, err := fd.Seek(offset, 0)
if err != nil {
panic(err)
}
fmt.Println("offsetreset =", offsetreset) //4096
offset, err = fd.Seek(0, 1)
if err != nil {
panic(err)
}
fmt.Println("offset =", offset) //4096
}
输出:
n = 0
offset = 4096
offsetreset = 4096
offset = 4096
答案 1 :(得分:0)
您可以增加扫描仪的缓冲区大小
例如:-
scanner := bufio.NewScanner(file)
buf := make([]byte, 0, 64*1024)
scanner.Buffer(buf, 1024*1024) //1024*1024 => 1mb max (you can change value here to read larger files
for scanner.Scan() {
// do your stuff
}