기존의 자식 io.Reader
의 버퍼링 된 판독기를 작성해야하지만 해당 판독기는 이미 자식으로부터 읽혀 버퍼링 된 데이터를 찾는 것을 지원해야합니다.버퍼링 된 판독기에서 검색
그래서 n
바이트가 이미 읽혀지면 리더를 재설정하여 0
을 오프셋하고 해당 청크를 다시 읽을 수 있기를 바랍니다.
불행히도 bufio.Reader
은 (는) 검색을 지원하지 않습니다.
표준을 지원하는 독자가 있습니까? 아니면 내 독자적으로 구현해야합니까?
기존의 자식 io.Reader
의 버퍼링 된 판독기를 작성해야하지만 해당 판독기는 이미 자식으로부터 읽혀 버퍼링 된 데이터를 찾는 것을 지원해야합니다.버퍼링 된 판독기에서 검색
그래서 n
바이트가 이미 읽혀지면 리더를 재설정하여 0
을 오프셋하고 해당 청크를 다시 읽을 수 있기를 바랍니다.
불행히도 bufio.Reader
은 (는) 검색을 지원하지 않습니다.
표준을 지원하는 독자가 있습니까? 아니면 내 독자적으로 구현해야합니까?
bufio
의 목적은 버퍼링 된 I/O를 제공하는 것입니다. 버퍼링 된 I/O는 시간 이동이 아닌 성능을위한 것입니다.
데이터를 바이트 조각으로 읽은 다음 bytes.Reader
을 사용하여 추가로 처리 할 수 있습니다.
오픈 도어를 찾고 나서 bufio.Reset()
을 사용하여 궁금한 점이 궁금했는데 이상적은 아닙니다. 우선, bufio.Reset
의 문서에 "버퍼링 된 데이터를 버리십시오"라고 쓰여 있지만 운영 체제에서도 최근에 읽은 파일 내용을 캐시하지 않습니다.
둘째, bufio가 지정된 파일 위치에서 읽기 및 버퍼링을 시작하지만 섹터 정렬은 고려하지 않기 때문에 시작 지점과 관계없이 한 번에 전체 버퍼를 버퍼링합니다. 따라서 버퍼 크기 (기본적으로 4096)가 파일 시스템의 클러스터 크기와 같다고 가정하고 시작 지점이 클러스터에 정렬되어 있지 않으면 bufio는 읽을 때마다 2 클러스터에서 읽습니다. 성능에 미치는 영향이 눈에 띄는 것은 아닙니다. 사실, 최대한 앞서서 읽음으로써, 나의 정렬 강박 관념이 산출 할 수있는 것보다 성능이 더 나을 수도 있습니다. (추구 후, 파일 위치는 4096의 배수에 반환하지 않는 것을 보여주는)
package main
import (
"bufio"
"crypto/md5"
"fmt"
"os"
)
func readBytes(r *bufio.Reader, block []byte) {
for i := 1; i < len(block); i++ {
var err error
block[i], err = r.ReadByte()
if err != nil {
panic(err)
}
}
}
func status(f *os.File, r *bufio.Reader, block []byte, what string) {
fpos, err := f.Seek(0, os.SEEK_CUR)
if err != nil {
panic(err)
}
fmt.Printf("%s: fpos=%5d, buffered=%4d, md5=%X\n", what, fpos, r.Buffered(), md5.Sum(block))
}
func main() {
f, err := os.Open(os.Args[0])
if err != nil {
panic(err)
}
defer func() { f.Close() }()
r := bufio.NewReader(f)
var block = make([]byte, 2000)
status(f, r, block, "initial")
readBytes(r, block)
status(f, r, block, "block 1")
readBytes(r, block)
status(f, r, block, "block 2")
readBytes(r, block)
status(f, r, block, "block 3")
f.Seek(2000, os.SEEK_SET) // return to start of buf1a
r.Reset(f)
readBytes(r, block)
status(f, r, block, "block 2")
readBytes(r, block)
status(f, r, block, "block 3")
readBytes(r, block)
status(f, r, block, "block 4")
}
전형적인 출력 :
이 코드는 실행 자체에서 몇 2,000 바이트 덩어리를 읽고,이 방법을 보여줍니다 생각
initial: fpos= 0, buffered= 0, md5=CF40A1DE3F93B4A025409B5EFA5AA210
block 1: fpos= 4096, buffered=2096, md5=C7015DD984AB85CCCBD206BA8243647D
block 2: fpos= 4096, buffered= 96, md5=E0D75F4A6DE681316515F5CD53F0D95C
block 3: fpos= 8192, buffered=2192, md5=7961B1A889E9793344374B3022314CD0
block 2: fpos= 6096, buffered=2096, md5=E0D75F4A6DE681316515F5CD53F0D95C
block 3: fpos= 6096, buffered= 96, md5=7961B1A889E9793344374B3022314CD0
block 4: fpos=10192, buffered=2192, md5=2A2F77C23EF4651E630855D9C3AA29DE
불행히도 내가 읽어야하는 파일은 청크로 읽히는 상대적으로 큰 다중 부분 파일이므로 그 이유는 모든 것을 메모리에로드해야하는'bytes.Reader'를 사용할 수 없기 때문입니다. 다음 사용자 지정 구현을 사용해야합니다. –
@ErikAigner : 맞춤 구현을 어떻게 진행 했습니까? 필자는 비슷한 상황에 있으며, CSV 데이터의'io.Reader' 바이트 스트림을 들여다보고 나서 csv.NewReader()로 전달하기 전에 구분자를 감지해야합니다. – DanielSmedegaardBuus