2013-12-16 42 views
4

我有一個名爲「DoSomething」的方法。 DoSomething將採用二進制源數據對其執行操作,並寫出二進制數據。 DoSomething需要足夠通用以處理源和目標的[]字節數組或文件句柄。要做到這一點,我試圖宣佈這樣的方法:從[]字節或文件io.WriteSeeker和io.ReadSeeker

func DoSomething(source *io.ReadSeeker, destination *io.WriteSeeker)

我已經實現了ReadSeeker和WriteSeeker與緩衝區的工作,用我自己的自定義,需要的方法(如果有一種方法可以自動做到這一點,我也很想聽到它)。 不幸的是,我似乎無法弄清楚如何從文件句柄中創建一個io.ReadSeeker或io.WriteSeeker。我相當肯定,必須有一些預先熟悉的方式來處理這個問題,而不必手動實施它們。這可能嗎?

回答

8

一個文件已經實現了這兩個。你可以這樣做:

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) 
} 

此外,你不需要傳遞指針到接口,這使得它更容易處理它們。

+1

謝謝!這應該是顯而易見的。 我可以在沒有手動實現所有方法的情況下從[]字節緩衝區創建ReadSeeker/WriteSeeker嗎? – shellster

+1

我以爲'bytes.Buffer'包會處理它,但顯然不是。在搜索引擎和字節上搜索谷歌組的帖子。所以,是的,如果你真的需要,你可能需要將它包裝在實現「Seek」的東西中。 –

+0

我寫了一個完全符合你要求的包。新的結構由'bytes.Buffer'支持並實現'io.Reader','io.Seeker','io.ReaderAt','io.Writer'等。pkg的主要目的是避免在數據不需要保存時使用文件(臨時或不臨時)。這是pkg:https://github.com/mattetti/filebuffer –

2

對於任何需要完成這樣的事情的人來說,這就是我最終的結果。這是不完整的,但它是我所需要的足夠接近:

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 
}