超出缓冲区读取

huangapple go评论146阅读模式
英文:

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))
}

Playground


Output:

First read got 12 bytes: some length 
Second read got 12 bytes: test string 

答案2

得分: 0

  1. 查看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)。

  1. 查看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 &amp;&amp; len(b.buf) &gt;= size {
		return b
	}
	if size &lt; minReadBufferSize {
		size = minReadBufferSize
	}
	return &amp;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,……

huangapple
  • 本文由 发表于 2013年8月27日 22:22:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/18468128.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定