2016-10-25 7 views
1

Goでネストされたzipファイル(zipファイルには別のzipファイルが含まれています)を処理するのには苦労しています。私はzipファイルを再帰させて、それに含まれているすべてのファイルを一覧表示しようとしています。アーカイブ/ zipでネストされたzipファイルを扱う

  • zip.NewReader
  • zip.OpenReader

OpenReaderは、ディスク上のファイルを開きます。

アーカイブ/ジッパーはあなたのzipファイルを処理するための2つのメソッドを提供します。 NewReaderは、io.ReaderAtとファイルサイズを受け入れます。これらのいずれかを使用してzipファイルを繰り返し処理するときは、zip内の各ファイルについてzip.Fileを取得します。ファイルfのファイル内容を取得するには、と呼び出してzip.ReadCloserとします。ネストされたzipファイルを開くには、NewReaderを使用する必要がありますが、zip.Filezip.ReadCloserio.ReaderAtインターフェイスを満たしていません。

zip.Fileio.ReaderAtzip.ReadCloserNewReaderのための要件を満たす必要がありますos.Fileあるプライベートフィールドfを持っているプラ​​イベートフィールドziprがあります。

私の質問:ディスク上のファイルに内容を書き込んだり、全体をメモリに読み込んだりすることなく、ネストされたzipファイルを開く方法はありますか?

必要なものはすべてzip.Fileで利用できますが、エクスポートされていないようです。私は何かを逃したことを望んでいる。

+1

を動作しない場合があります私はそれを 'bytes.Buffer'またはディスクにコピーするのが最も簡単なことを恐れています。ネストしたzipの大きさはどれくらいですか? – captncraig

+0

https://godoc.org/golang.org/x/tools/godoc/vfs/zipfsのapiもちょっとしたものです。わからない。 – captncraig

+0

@captncraigこれは小さなスキャンプログラム用ですので、遭遇するZIPファイルがわかりません。私はこれがどれほど一般的なのかよく分かりません。私はストリームを使ってすべてを一緒に繋ぐことができたと感じました。 'bytes.Buffer'を呼ぶといいです。私はそれにアクセスできるので、すべてを読む前にファイルサイズを調べることができます。 – freb

答えて

0

どのようにあなたが逆方向に行くことにした場合は再初期化io.Readerからio.ReaderAtについて:(このコードは、主にテストされていないが、うまくいけばあなたのアイデアを得る)

package main 

import (
    "io" 
    "io/ioutil" 
    "os" 
    "strings" 
) 

type inefficientReaderAt struct { 
    rdr io.ReadCloser 
    cur int64 
    initer func() (io.ReadCloser, error) 
} 

func newInefficentReaderAt(initer func() (io.ReadCloser, error)) *inefficientReaderAt { 
    return &inefficientReaderAt{ 
     initer: initer, 
    } 
} 

func (r *inefficientReaderAt) Read(p []byte) (n int, err error) { 
    n, err = r.rdr.Read(p) 
    r.cur += int64(n) 
    return n, err 
} 

func (r *inefficientReaderAt) ReadAt(p []byte, off int64) (n int, err error) { 
    // reset on rewind 
    if off < r.cur || r.rdr == nil { 
     r.cur = 0 
     r.rdr, err = r.initer() 
     if err != nil { 
      return 0, err 
     } 
    } 

    if off > r.cur { 
     sz, err := io.CopyN(ioutil.Discard, r.rdr, off-r.cur) 
     n = int(sz) 
     if err != nil { 
      return n, err 
     } 
    } 

    return r.Read(p) 
} 

func main() { 
    r := newInefficentReaderAt(func() (io.ReadCloser, error) { 
     return ioutil.NopCloser(strings.NewReader("ABCDEFG")), nil 
    }) 

    io.Copy(os.Stdout, io.NewSectionReader(r, 0, 3)) 
    io.Copy(os.Stdout, io.NewSectionReader(r, 1, 3)) 
} 

あなたは主に前方にこれを移動する場合は、おそらくうまく動作。特にバッファードリーダーを使用している場合。

  • 私はこれがio.ReaderAt保証違反していることに注意してください:https://godoc.org/io#ReaderFrom、つまりそれはReadAtに平行コールを許可していないが、フルの読み取りにブロックされませんので、これはさえきちんと
関連する問題