英文:
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,……
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论