golang bufio
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
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.