golang bufio

3720 단어
Golang 라이브러리 함수에 bufio 모듈 코드를 테스트하고 Readline은'절분 데이터'에 근거하여
package main

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"time"
)

type Reader struct {
	buf          []byte
	rd           io.Reader // reader provided by the client
	r, w         int       // buf read and write positions
	err          error
	lastByte     int
	lastRuneSize int
}

const minReadBufferSize = 16
const maxConsecutiveEmptyReads = 100

var errNegativeRead = errors.New("bufio: reader returned negative count from Read")
var ErrBufferFull = errors.New("bufio: buffer full")

func (b *Reader) readErr() error {
	err := b.err
	b.err = nil
	return err
}

// fill reads a new chunk into the buffer.
func (b *Reader) fill() {
	// Slide existing data to beginning.
	//fmt.Printf("reader r %v
", b.r) if b.r > 0 { copy(b.buf, b.buf[b.r:b.w]) b.w -= b.r b.r = 0 } if b.w >= len(b.buf) { panic("bufio: tried to fill full buffer") } // Read new data: try a limited number of times. // , 100 for i := maxConsecutiveEmptyReads; i > 0; i-- { n, err := b.rd.Read(b.buf[b.w:]) //fmt.Printf(" count %v 
", n) if n < 0 { panic(errNegativeRead) } b.w += n if err != nil { b.err = err return } if n > 0 { return } } b.err = io.ErrNoProgress } func (b *Reader) Buffered() int { return b.w - b.r } func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { for { // Search buffer. //fmt.Printf("bytes index %v err %v 
", bytes.IndexByte(b.buf[b.r:b.w], delim), b.err) if i := bytes.IndexByte(b.buf[b.r:b.w], delim); i >= 0 { line = b.buf[b.r : b.r+i+1] //fmt.Printf("line is %v 
", string(line)) b.r += i + 1 break } // Pending error? if b.err != nil { line = b.buf[b.r:b.w] b.r = b.w err = b.readErr() break } // Buffer full? //fmt.Printf("bufio buffered %v len buf %v
", b.Buffered(), len(b.buf)) if b.Buffered() >= len(b.buf) { b.r = b.w line = b.buf err = ErrBufferFull break } b.fill() // buffer is not full } // Handle last byte, if any. if i := len(line) - 1; i >= 0 { b.lastByte = int(line[i]) b.lastRuneSize = -1 } return } func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) { line, err = b.ReadSlice('
') if err == ErrBufferFull { // Handle the case where "\r
" straddles the buffer. if len(line) > 0 && line[len(line)-1] == '\r' { // Put the '\r' back on buf and drop it from line. // Let the next call to ReadLine check for "\r
". if b.r == 0 { // should be unreachable panic("bufio: tried to rewind past start of buffer") } b.r-- line = line[:len(line)-1] } return line, true, nil } if len(line) == 0 { if err != nil { line = nil } return } err = nil if line[len(line)-1] == '
' { drop := 1 if len(line) > 1 && line[len(line)-2] == '\r' { drop = 2 } line = line[:len(line)-drop] } return } func main() { reader := bytes.NewReader([]byte("absc\r
ddd
")) b := &Reader{ buf:          make([]byte, 100), rd:           reader, lastByte:     -1, lastRuneSize: -1, } for { line, isPrefix, err := b.ReadLine() fmt.Printf("line %v / prefix %v / err %v
", string(line), isPrefix, err) if err == io.EOF { break } time.Sleep(1 * time.Second) } }

결과 출력:
line absc / prefix false / err <nil>
line ddd / prefix false / err <nil>
line  / prefix false / err EOF

좋은 웹페이지 즐겨찾기