英文:
Reading beyond buffer
问题
我有一个大小为bufferSize的缓冲区,我从中以blockSize的块读取数据,然而,当blockSize超过bufferSize时,这会导致一些(对我来说)意外的行为。
我在这里放置了代码:
http://play.golang.org/p/Ra2jicYHPu
为什么第二个块只有4个字节?这里发生了什么?
我期望Read总是返回byteArray的字节数量,并且如果超过缓冲区,它会通过将缓冲区指针设置为byteArray之后,并将剩余的缓冲区+超出部分直到新的缓冲区指针处来处理这种情况。
英文:
I have a buffer of size bufferSize from which I read in chunks of blockSize, however, this yields some (to me) unexpected behavior, when the blockSize goes beyond the bufferSize.
I've put the code here:
http://play.golang.org/p/Ra2jicYHPu
Why does the second chunk only give 4 bytes? What's happening here?
I'd expect Read to always give the amount of bytes len(byteArray), and if it goes beyond the buffer, it'll handle that situation by setting the pointer in the buffer to after byteArray, and putting the rest of the buffer + whatever is beyond until the new buffer pointer.
答案1
得分: 1
你的期望不基于bufio.Reader的任何文档行为。如果你想要“Read始终返回字节数len(byteArray)”,你必须使用io.ReadAtLeast。
package main
import (
"bufio"
"fmt"
"io"
"strings"
)
const bufSize = 10
const blockSize = 12
func main() {
s := strings.NewReader("some length test string buffer boom")
buffer := bufio.NewReaderSize(s, bufSize)
b := make([]byte, blockSize)
n, err := io.ReadAtLeast(buffer, b, blockSize)
if err != nil {
fmt.Println(err)
}
fmt.Printf("First read got %d bytes: %s\n", n, string(b))
d := make([]byte, blockSize)
n, err = io.ReadAtLeast(buffer, d, blockSize)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Second read got %d bytes: %s\n", n, string(d))
}
输出:
First read got 12 bytes: some length
Second read got 12 bytes: test string
英文:
Your expectations are not based on any documented behavior of bufio.Reader. If you want "Read to always give the amount of bytes len(byteArray)" you must use io.ReadAtLeast.
package main
import (
"bufio"
"fmt"
"io"
"strings"
)
const bufSize = 10
const blockSize = 12
func main() {
s := strings.NewReader("some length test string buffer boom")
buffer := bufio.NewReaderSize(s, bufSize)
b := make([]byte, blockSize)
n, err := io.ReadAtLeast(buffer, b, blockSize)
if err != nil {
fmt.Println(err)
}
fmt.Printf("First read got %d bytes: %s\n", n, string(b))
d := make([]byte, blockSize)
n, err = io.ReadAtLeast(buffer, d, blockSize)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Second read got %d bytes: %s\n", n, string(d))
}
Output:
First read got 12 bytes: some length
Second read got 12 bytes: test string
答案2
得分: 0
- 查看buffio.NewReaderSize的代码:
func NewReaderSize(rd io.Reader, size int) *Reader {
// 是否已经是Reader类型?
b, ok := rd.(*Reader)
if ok && len(b.buf) >= size {
return b
}
if size < minReadBufferSize {
size = minReadBufferSize
}
return &Reader{
buf: make([]byte, size),
rd: rd,
lastByte: -1,
lastRuneSize: -1,
}
}
strings.NewReader返回一个strings.Reader,所以缓冲区(由bufio.NewReaderSize返回)的buf大小为minReadBufferSize(值为16)。
- 查看bufio.Read的代码:
func (b *Reader) Read(p []byte) (n int, err error) {
// ...
copy(p[0:n], b.buf[b.r:])
b.r += n
b.lastByte = int(b.buf[b.r-1])
b.lastRuneSize = -1
return n, nil
}
复制的源数据是b.buf[b.r:],当你第一次调用Read时,b.r=12,...
英文:
1.see the code of buffio.NewReaderSize
func NewReaderSize(rd io.Reader, size int) *Reader {
// Is it already a Reader?
b, ok := rd.(*Reader)
if ok && len(b.buf) >= size {
return b
}
if size < minReadBufferSize {
size = minReadBufferSize
}
return &Reader{
buf: make([]byte, size),
rd: rd,
lastByte: -1,
lastRuneSize: -1,
}
}
strings.NewReader return a strings.Reader,so the buffer's (returned by bufio.NewReaderSize ) buf has minReadBufferSize(val is 16)
2.see code of bufio.Read
func (b *Reader) Read(p []byte) (n int, err error) {
……
copy(p[0:n], b.buf[b.r:])
b.r += n
b.lastByte = int(b.buf[b.r-1])
b.lastRuneSize = -1
return n, nil
}
copy src is b.buf[b.r:],when your first Read,b.r=12,……
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论