英文:
io.WriteSeeker and io.ReadSeeker from []byte or file
问题
我有一个名为"DoSomething"的方法。DoSomething将对二进制源数据执行操作,并将结果写入二进制数据。DoSomething需要足够通用,能够处理[]byte数组或文件句柄作为源和目标。为了实现这一点,我尝试像这样声明该方法:
func DoSomething(source *io.ReadSeeker, destination *io.WriteSeeker)
我已经实现了用于处理缓冲区的ReadSeeker和WriteSeeker,使用了我自己的自定义必需方法(如果有一种自动完成这个过程的方法,我也很想知道)。不幸的是,我似乎无法从文件句柄创建io.ReadSeeker或io.WriteSeeker。我相当确定必须有一些现成的方法来处理这个问题,而不必手动实现它们。这种可能吗?
英文:
I have a method called "DoSomething". DoSomething will take binary source data perform an operation on it, and write out binary data. DoSomething needs to be generic enough to handle either a []byte array or a file handle for both the source and destination. To accomplish this, I have attempted to declare the method like this:
func DoSomething(source *io.ReadSeeker, destination *io.WriteSeeker)
I have implemented the ReadSeeker and WriteSeeker for working with buffers, using my own custom, required methods (if there is a way to automatically accomplish this, I'd love to hear about it as well).
Unfortunately, I can't seem to figure out how to create either an io.ReadSeeker or io.WriteSeeker from a file handle. I'm fairly sure there must be some pre-cooked way of handling this without having to manually implement them. Is this possible?
答案1
得分: 14
一个文件已经实现了这两个功能。你可以像这样做:
package main
import (
"fmt"
"io"
"os"
)
func main() {
f, err := os.Open("test.txt")
if err != nil {
fmt.Println(err)
}
defer f.Close()
f2, err := os.Create("test2.txt")
if err != nil {
fmt.Println(err)
}
defer f2.Close()
DoSomething(f, f2)
}
func DoSomething(source io.ReadSeeker, destination io.WriteSeeker) {
io.Copy(destination, source)
}
另外,你不需要传递接口的指针,这样处理起来更容易。
英文:
A file already implements both of those. You can do something like this:
package main
import (
"fmt"
"io"
"os"
)
func main() {
f, err := os.Open("test.txt")
if err != nil {
fmt.Println(err)
}
defer f.Close()
f2, err := os.Create("test2.txt")
if err != nil {
fmt.Println(err)
}
defer f2.Close()
DoSomething(f, f2)
}
func DoSomething(source io.ReadSeeker, destination io.WriteSeeker) {
io.Copy(destination, source)
}
Also, you don't need to pass pointers to interfaces, which makes it easier to deal with them.
答案2
得分: 9
对于其他需要完成类似任务的人,这是我最终得到的代码。它并不完整,但对于我所需的功能已经足够接近了:
package filebuffer
import (
"bytes"
"errors"
)
type FileBuffer struct {
Buffer bytes.Buffer
Index int64
}
func NewFileBuffer() FileBuffer {
return FileBuffer{}
}
func (fbuffer *FileBuffer) Bytes() []byte {
return fbuffer.Buffer.Bytes()
}
func (fbuffer *FileBuffer) Read(p []byte) (int, error) {
n, err := bytes.NewBuffer(fbuffer.Buffer.Bytes()[fbuffer.Index:]).Read(p)
if err == nil {
if fbuffer.Index+int64(len(p)) < int64(fbuffer.Buffer.Len()) {
fbuffer.Index += int64(len(p))
} else {
fbuffer.Index = int64(fbuffer.Buffer.Len())
}
}
return n, err
}
func (fbuffer *FileBuffer) Write(p []byte) (int, error) {
n, err := fbuffer.Buffer.Write(p)
if err == nil {
fbuffer.Index = int64(fbuffer.Buffer.Len())
}
return n, err
}
func (fbuffer *FileBuffer) Seek(offset int64, whence int) (int64, error) {
var err error
var Index int64 = 0
switch whence {
case 0:
if offset >= int64(fbuffer.Buffer.Len()) || offset < 0 {
err = errors.New("Invalid Offset.")
} else {
fbuffer.Index = offset
Index = offset
}
default:
err = errors.New("Unsupported Seek Method.")
}
return Index, err
}
然后你可以像这样使用它:
destination := filebuffer.NewFileBuffer()
source, err := os.Open(pathString)
if err != nil {
return nil, err
}
defer source.Close()
if _, err := encrypter.Decrypt(source, &destination, password); err != nil {
return nil, err
}
希望对你有帮助!
英文:
For anyone else who needs to accomplish something like this, here's what I ended up with. It isn't complete, but it is close enough for what I needed:
package filebuffer
import (
"bytes"
"errors"
)
type FileBuffer struct {
Buffer bytes.Buffer
Index int64
}
func NewFileBuffer() FileBuffer {
return FileBuffer{}
}
func (fbuffer *FileBuffer) Bytes() []byte {
return fbuffer.Buffer.Bytes()
}
func (fbuffer *FileBuffer) Read(p []byte) (int, error) {
n, err := bytes.NewBuffer(fbuffer.Buffer.Bytes()[fbuffer.Index:]).Read(p)
if err == nil {
if fbuffer.Index+int64(len(p)) < int64(fbuffer.Buffer.Len()) {
fbuffer.Index += int64(len(p))
} else {
fbuffer.Index = int64(fbuffer.Buffer.Len())
}
}
return n, err
}
func (fbuffer *FileBuffer) Write(p []byte) (int, error) {
n, err := fbuffer.Buffer.Write(p)
if err == nil {
fbuffer.Index = int64(fbuffer.Buffer.Len())
}
return n, err
}
func (fbuffer *FileBuffer) Seek(offset int64, whence int) (int64, error) {
var err error
var Index int64 = 0
switch whence {
case 0:
if offset >= int64(fbuffer.Buffer.Len()) || offset < 0 {
err = errors.New("Invalid Offset.")
} else {
fbuffer.Index = offset
Index = offset
}
default:
err = errors.New("Unsupported Seek Method.")
}
return Index, err
}
You then use it like this:
destination := filebuffer.NewFileBuffer()
source, err := os.Open(pathString)
if err != nil {
return nil, err
}
defer source.Close()
if _, err := encrypter.Decrypt(source, &destination, password); err != nil {
return nil, err
}
答案3
得分: 0
对于需要的任何人,这是一个支持所有I/O操作的io.ReadWriteSeeker实现:
import (
"errors"
"fmt"
"io"
)
// 用于测试目的实现io.ReadWriteSeeker。
type FileBuffer struct {
buffer []byte
offset int64
}
// 创建一个新的缓冲区,用于测试目的实现io.ReadWriteSeeker。
func NewFileBuffer(initial []byte) FileBuffer {
if initial == nil {
initial = make([]byte, 0, 100)
}
return FileBuffer{
buffer: initial,
offset: 0,
}
}
func (fb *FileBuffer) Bytes() []byte {
return fb.buffer
}
func (fb *FileBuffer) Len() int {
return len(fb.buffer)
}
func (fb *FileBuffer) Read(b []byte) (int, error) {
available := len(fb.buffer) - int(fb.offset)
if available == 0 {
return 0, io.EOF
}
size := len(b)
if size > available {
size = available
}
copy(b, fb.buffer[fb.offset:fb.offset+int64(size)])
fb.offset += int64(size)
return size, nil
}
func (fb *FileBuffer) Write(b []byte) (int, error) {
copied := copy(fb.buffer[fb.offset:], b)
if copied < len(b) {
fb.buffer = append(fb.buffer, b[copied:]...)
}
fb.offset += int64(len(b))
return len(b), nil
}
func (fb *FileBuffer) Seek(offset int64, whence int) (int64, error) {
var newOffset int64
switch whence {
case io.SeekStart:
newOffset = offset
case io.SeekCurrent:
newOffset = fb.offset + offset
case io.SeekEnd:
newOffset = int64(len(fb.buffer)) + offset
default:
return 0, errors.New("未知的Seek方法")
}
if newOffset > int64(len(fb.buffer)) || newOffset < 0 {
return 0, fmt.Errorf("无效的偏移量 %d", offset)
}
fb.offset = newOffset
return newOffset, nil
}
希望对你有帮助!
英文:
For anyone who needs it, here's an implementation of io.ReadWriteSeeker, that supports all I/O operations:
import (
"errors"
"fmt"
"io"
)
// Implements io.ReadWriteSeeker for testing purposes.
type FileBuffer struct {
buffer []byte
offset int64
}
// Creates new buffer that implements io.ReadWriteSeeker for testing purposes.
func NewFileBuffer(initial []byte) FileBuffer {
if initial == nil {
initial = make([]byte, 0, 100)
}
return FileBuffer{
buffer: initial,
offset: 0,
}
}
func (fb *FileBuffer) Bytes() []byte {
return fb.buffer
}
func (fb *FileBuffer) Len() int {
return len(fb.buffer)
}
func (fb *FileBuffer) Read(b []byte) (int, error) {
available := len(fb.buffer) - int(fb.offset)
if available == 0 {
return 0, io.EOF
}
size := len(b)
if size > available {
size = available
}
copy(b, fb.buffer[fb.offset:fb.offset+int64(size)])
fb.offset += int64(size)
return size, nil
}
func (fb *FileBuffer) Write(b []byte) (int, error) {
copied := copy(fb.buffer[fb.offset:], b)
if copied < len(b) {
fb.buffer = append(fb.buffer, b[copied:]...)
}
fb.offset += int64(len(b))
return len(b), nil
}
func (fb *FileBuffer) Seek(offset int64, whence int) (int64, error) {
var newOffset int64
switch whence {
case io.SeekStart:
newOffset = offset
case io.SeekCurrent:
newOffset = fb.offset + offset
case io.SeekEnd:
newOffset = int64(len(fb.buffer)) + offset
default:
return 0, errors.New("Unknown Seek Method")
}
if newOffset > int64(len(fb.buffer)) || newOffset < 0 {
return 0, fmt.Errorf("Invalid Offset %d", offset)
}
fb.offset = newOffset
return newOffset, nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论