从golang中的缓冲读取器读取特定的字节数

时间:2012-12-01 15:29:54

标签: go bufferedreader peek

我从 bufio 包中了解golang的具体功能。

func (b *Reader) Peek(n int) ([]byte, error)
  

Peek返回接下来的n个字节而不推进阅读器。字节   在下次阅读通话时停止有效。如果Peek返回少于n   字节,它还返回一个错误,解释为什么读取很短。该   如果n大于b的缓冲区大小,则错误为ErrBufferFull。

我需要能够从阅读器中读取特定数量的字节,将推动阅读器。基本上,与上面的功能相同,但它推动了读者。有人知道如何做到这一点吗?

6 个答案:

答案 0 :(得分:67)

请注意,bufio.Read方法最多只调用一次基础io.Read,这意味着它可以返回n < len(p),而不会达到EOF。如果您想要准确读取len(p)字节或因错误而失败,您可以使用io.ReadFull这样:

n, err := io.ReadFull(reader, p)

即使读者已缓冲,也可以使用。

答案 1 :(得分:21)

func (b *Reader) Read(p []byte) (n int, err error)

http://golang.org/pkg/bufio/#Reader.Read

读取的字节数将限制为len(p)

答案 2 :(得分:5)

我更喜欢Read(),特别是如果你要阅读任何类型的文件,它也可以用于以块的形式发送数据,下面是一个展示如何使用它的例子

fs, err := os.Open("fileName"); 

if err != nil{
    fmt.Println("error reading file")
    return
}

defer fs.Close()

reader := bufio.NewReader(fs)

buf := make([]byte, 1024)

for{
    v, _ := reader.Read(buf) //ReadString and ReadLine() also applicable or alternative

    if v == 0{
        return
    }
    //in case it is a string file, you could check its content here...
    fmt.Print(string(buf))
}

答案 3 :(得分:3)

将一个n字节大小的缓冲区传递给阅读器。

答案 4 :(得分:0)

要执行此操作,您只需要使用

创建一个字节切片并将read数据放入此切片中
n := 512
buff := make([]byte, n)
fs.Read(buff)  // fs is your reader. Can be like this fs, _ := os.Open('file')

func (b *Reader) Read(p []byte) (n int, err error)

  

读取将数据读入p。它返回读入p的字节数。   这些字节最多取自底层Reader上的一个Read,   因此n可能小于len(p)

答案 5 :(得分:0)

TLDR:

my42bytes, err := ioutil.ReadAll(io.LimitReader(myReader, 42))

完整答案:

@monicuta提到了io.ReadFull,效果很好。在这里,我提供了另一种方法。它通过将ioutil.ReadAllio.LimitReader链接在一起来工作。让我们先阅读文档:

$ go doc ioutil.ReadAll
func ReadAll(r io.Reader) ([]byte, error)
     ReadAll reads from r until an error or EOF and returns the data it read. A
     successful call returns err == nil, not err == EOF. Because ReadAll is
     defined to read from src until EOF, it does not treat an EOF from Read as an
     error to be reported. 

$ go doc io.LimitReader
func LimitReader(r Reader, n int64) Reader
     LimitReader returns a Reader that reads from r but stops with EOF after n
     bytes. The underlying implementation is a *LimitedReader.

因此,如果您想从myReader获取42个字节,请执行此操作

import (
        "io"
        "io/ioutil"
)

func main() {
        // myReader := ...
        my42bytes, err := ioutil.ReadAll(io.LimitReader(myReader, 42))
        if err != nil {
                panic(err)
        }
        //...
}

以下是与io.ReadFull等效的代码

$ go doc io.ReadFull
func ReadFull(r Reader, buf []byte) (n int, err error)
    ReadFull reads exactly len(buf) bytes from r into buf. It returns the number
    of bytes copied and an error if fewer bytes were read. The error is EOF only
    if no bytes were read. If an EOF happens after reading some but not all the
    bytes, ReadFull returns ErrUnexpectedEOF. On return, n == len(buf) if and
    only if err == nil. If r returns an error having read at least len(buf)
    bytes, the error is dropped.
import (
        "io"
)

func main() {
        // myReader := ...
        buf := make([]byte, 42)
        _, err := io.ReadFull(myReader, buf)
        if err != nil {
                panic(err)
        }
        //...
}

io.ReadFull相比,优点是您不需要手动创建buf,其中len(buf)是要读取的字节数,然后传递{{ 1}}作为阅读时的论证

相反,您只需告诉buf,您最多要从io.LimitReader中获取42个字节,然后调用myReader读取全部内容,并将结果作为字节片返回。如果成功,则保证返回的切片长度为42。