2016-08-11 14 views
3

私はbufio.NewScannerを使って次の関数を使ってファイルを1行ずつ読み込もうとしていました。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バイトの場合

を、
が、大きなファイルのためにちょうど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 
関連する問題