doukong9982
2012-12-01 15:29
浏览 510
已采纳

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

I am aware of the specific function in golang from the bufio package.

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

Peek returns the next n bytes without advancing the reader. The bytes stop being valid at the next read call. If Peek returns fewer than n bytes, it also returns an error explaining why the read is short. The error is ErrBufferFull if n is larger than b's buffer size.

I need to be able to read a specific number of bytes from a Reader that will advance the reader. Basically, identical to the function above, but it advances the reader. Does anybody know how to accomplish this?

图片转代码服务由CSDN问答提供 功能建议

我知道 bufio 包中的golang中的特定功能。

  func(b *阅读器)Peek(n int)([] byte,error)
   
 
 

Peek返回下n个字节,不提高阅读器。 字节 在下一个读取调用时停止有效。 如果Peek返回的字节数少于n 个字节,则它还会返回一个错误,解释读取短的原因。 如果n大于b的缓冲区大小,则 错误为ErrBufferFull。

我需要能够从读取器读取特定数量的字节 >将提升读者。 基本上,与上面的功能相同,但是它使阅读器更高级。 有人知道如何做到这一点吗?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

6条回答 默认 最新

  • doulan0297 2013-10-28 23:25
    已采纳

    Note that the bufio.Read method calls the underlying io.Read at most once, meaning that it can return n < len(p), without reaching EOF. If you want to read exactly len(p) bytes or fail with an error, you can use io.ReadFull like this:

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

    This works even if the reader is buffered.

    打赏 评论
  • douyi2664 2012-12-01 16:24

    Pass a n-bytes sized buffer to the reader.

    打赏 评论
  • dqybeh2884 2012-12-01 16:44
    func (b *Reader) Read(p []byte) (n int, err error)
    

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

    The number of bytes read will be limited to len(p)

    打赏 评论
  • douxuanjie2692 2013-12-02 18:12

    I am prefering Read() especially if you are going to read any type of files and it could be also useful in sending data in chunks, below is an example to show how it is used

    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))
    }
    
    打赏 评论
  • dongyou1926 2016-07-04 06:12

    To do this you just need to create a byte slice and read the data into this slice with

    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)

    Read reads data into p. It returns the number of bytes read into p. The bytes are taken from at most one Read on the underlying Reader, hence n may be less than len(p)

    打赏 评论
  • dongxianshuai8927 2019-05-15 03:45

    TLDR:

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

    Full answer:

    @monicuta mentioned io.ReadFull which works great. Here I provide another method. It works by chaining ioutil.ReadAll and io.LimitReader together. Let's read the doc first:

    $ 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.
    

    So if you want to get 42 bytes from myReader, you do this

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

    Here is the equivalent code with 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)
            }
            //...
    }
    

    Compared to io.ReadFull, an advantage is that you don't need to manually make a buf, where len(buf) is the number of bytes you want to read, then pass buf as an argument when you Read

    Instead you simply tell io.LimitReader you want at most 42 bytes from myReader, and call ioutil.ReadAll to read them all, returning the result as a slice of bytes. If successful, the returned slice is guaranteed to be of length 42.

    打赏 评论

相关推荐 更多相似问题