我从 bufio 包中了解golang的具体功能。
func (b *Reader) Peek(n int) ([]byte, error)
Peek返回接下来的n个字节而不推进阅读器。字节 在下次阅读通话时停止有效。如果Peek返回少于n 字节,它还返回一个错误,解释为什么读取很短。该 如果n大于b的缓冲区大小,则错误为ErrBufferFull。
我需要能够从阅读器中读取特定数量的字节,将推动阅读器。基本上,与上面的功能相同,但它推动了读者。有人知道如何做到这一点吗?
答案 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.ReadAll
和io.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。