将`bufio.Reader`转换为`io.ReadWriteCloser`。

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

convert from `bufio.Reader` to `io.ReadWriteCloser`

问题

我有一个io.ReadWriteCloser,我想在不推进读取器的情况下查看其中的内容,

所以我正在使用

bi := bufio.NewReader(i)
bi.Peek(1)

到目前为止还好,但是后来当我想要重新使用原始的io.ReadWriteCloser (i)时,它只有EOF

所以我的问题是如何将bufio.Reader转换回io.ReadWriteCloser

英文:

I have an io.ReadWriteCloser in which I want to peek into it without advancing the reader,

so I am using

bi := bufio.NewReader(i)
bi.Peek(1)

So far so good, but later when I want to reuse the original io.ReadWriteCloser (i) it has only EOF.

So my question is how to convert back from bufio.Reader back to io.ReadWriteCloser

答案1

得分: 3

因为bufio.Reader从底层读取器缓冲数据,所以在调用Peek后,应用程序必须从bufio.Reader中读取。

要获得执行此操作的io.ReadWriteCloser,请包装bufio.Reader和原始的io.ReadWriteCloser:

// BufferedReadWriteCloser具有*bufio.Reader和io.ReadWriteCloser的所有方法。
type BufferedReadWriteCloser struct {
*bufio.Reader
io.ReadWriteCloser
}

func (rw *BufferedReadWriteCloser) Read(p []byte) (int, error) {
return rw.Reader.Read(p)
}

以下是如何使用它的示例:

rw := &BufferedReadWriteCloser{bufio.NewReader(i), i}
p, err := rw.Peek(1)

rw的值满足io.ReadWriteCloser接口的要求。

并不要求或假设io.ReadWriteCloser具有Seek方法。

英文:

Because the bufio.Reader buffers data from the underlying reader, the application must read from the bufio.Reader after the call to Peek.

To get an io.ReadWriteCloser that does this, wrap the bufio.Reader and the original io.ReadWriteCloser:

// BufferedReadWriteCloser has all of the methods
// from *bufio.Reader and io.ReadWriteCloser.
type BufferedReadWriteCloser struct {
	*bufio.Reader
	io.ReadWriteCloser
}

func (rw *BufferedReadWriteCloser) Read(p []byte) (int, error) {
	return rw.Reader.Read(p)
}

Here's how to use it:

rw := &BufferedReadWriteCloser{bufio.NewReader(i), i}
p, err := rw.Peek(1)

The value of rw satisfies the io.ReadWriteCloser interface.

There is no requirement or assumption that the io.ReadWriteCloser has a Seek method.

答案2

得分: 0

如上面我的评论中提到的,你需要访问原始读取器的Seek方法。这意味着将读取器作为io.ReadWriteCloser传递是不够的。话虽如此,下面的辅助函数可能是一个解决方法:

func peek(r io.Reader, n int) ([]byte, error) {
	bi := bufio.NewReader(r)
	peeked, err := bi.Peek(n)
	if err != nil {
		return nil, err
	}
    // 使用类型断言来检查r是否实现了io.Seeker接口。如果是,则使用它来重置偏移量。
	if seeker, ok := r.(io.Seeker); ok {
		seeker.Seek(0, 0)
	}
	return peeked, nil
}

现在你可以将io.ReadWriteCloser传递给这个peek函数。peek函数会检查读取器是否实现了Seek方法。如果实现了Seek方法,peek函数将调用它。

英文:

As mentioned in my comment above, you need access to the original reader's Seek method. This means that passing the reader around as an io.ReadWriteCloser is insufficient. Having said that, the following helper function may be a workaround:

func peek(r io.Reader, n int) ([]byte, error) {
	bi := bufio.NewReader(r)
	peeked, err := bi.Peek(n)
	if err != nil {
		return nil, err
	}
    // Use type assertion to check if r implements the 
    // io.Seeker interface. If it does, then use it to
    // reset the offset.
	if seeker, ok := r.(io.Seeker); ok {
		seeker.Seek(0, 0)
	}
	return peeked, nil
}

Now you can pass the io.ReadWriteCloser to this peek function. The peek function checks if the reader happens to implement the Seek method. If the Seek method is implemented, then peek will call it.

huangapple
  • 本文由 发表于 2023年2月16日 08:56:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/75466833.html
匿名

发表评论

匿名网友

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

确定