2016-08-11 3 views
3

bufio.NewScanner을 사용하여 다음 함수를 사용하여 파일을 한 줄씩 읽으려고했습니다. Golang의 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 메모리에 전체 파일을 읽고 않으며, 반복? 그렇다면 줄 단위로 읽을 수있는 더 좋은 방법이 있습니까?

+4

아니요, 기본 버퍼 크기는 4096 바이트입니다. 큰 파일로 시도해보십시오. – JimB

답변

4

func (s *Scanner) Buffer(buf []byte, max int) 문서 참조 :

버퍼를 사용하는 초기 버퍼를 설정할 때 스캐닝 및 스캐닝 동안 할당 될 수있다 버퍼의 최대 크기 . 토큰 크기가 최대 이고 최대 값이 cap(buf)입니다.
max <= cap(buf) 인 경우 스캔은이 버퍼만을 사용하며 할당하지 않습니다.

기본적으로 스캔은 내부 버퍼를 사용하고 최대 토큰 을 MaxScanTokenSize으로 설정합니다.

검사가 시작된 후 호출되면 버퍼 패닉이 발생합니다.

: 그리고

MaxScanTokenSize 사용자가 명시 적으로 Scan.Buffer 버퍼를 제공 않는 토큰을 버퍼링하는 데 사용되는 최대 크기이다. 실제 최대 토큰 크기는 버퍼가 포함되어야 할 수도 있으므로 더 작을 수도 있습니다 (예 : ).

MaxScanTokenSize = 64 * 1024 

startBufSize = 4096 // Size of initial allocation for buffer. 

@JimB는 단지 버퍼 사이즈 읽기 말했듯 아니,이 테스트 샘플을 참조하십시오보다 작은 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 

} 

출력 :

단지 4096 바이트,
이 큰 파일이 시도를 읽고
n = 0 

offset = 4096 
offsetreset = 4096 
offset = 4096