我很难处理Go中的嵌套zip文件(其中zip文件包含另一个zip文件)。我正在尝试恢复一个zip文件并列出它包含的所有文件。
zip /zip为您提供了处理zip文件的两种方法:
OpenReader在磁盘上打开一个文件。NewReader接受io.ReaderAt和文件大小。当您使用这两个文件中的任何一个迭代压缩文件时,您将为zip中的每个文件提取一个zip.File。要获取文件f的文件内容,您可以调用f.Open,这将给您提供一个zip.ReadCloser。要打开嵌套的zip文件,我需要使用NewReader,但是zip.File和zip.ReadCloser不能满足io.ReaderAt接口。
zip.File有一个专用字段zipr,它是一个io.ReaderAt,zip.ReadCloser有一个私有字段f,它是一个满足NewReader需求的os.File。
我的问题是:是否有任何方法可以打开嵌套的zip文件,而不首先将内容写入磁盘上的文件,或者将全部内容读入内存。
看起来,所需的一切都可以在zip.File中使用,但不能导出。我希望我错过了什么。
发布于 2016-10-27 02:27:57
如果您决定向后返回,那么从一个重新初始化的io.ReaderAt中得到一个io.Reader怎么样?(这段代码基本上没有经过测试,但希望您能理解)
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的并行调用,也不阻止完全读取,因此这甚至可能无法正常工作。发布于 2019-05-12 12:46:22
我遇到了同样的需要,想出了以下方法,不确定它是否对你有帮助:
// NewZipFromReader ...
func NewZipFromReader(file io.ReadCloser, size int64) (*zip.Reader, error) {
in := file.(io.Reader)
if _, ok := in.(io.ReaderAt); ok != true {
buffer, err := ioutil.ReadAll(in)
if err != nil {
return nil, err
}
in = bytes.NewReader(buffer)
size = int64(len(buffer))
}
reader, err := zip.NewReader(in.(io.ReaderAt), size)
if err != nil {
return nil, err
}
return reader, nil
}因此,如果file不实现io.ReaderAt,则会将整个内容读入缓冲区。
处理ZIP炸弹可能不安全,对于大于RAM的文件,OOM也会失败。
https://stackoverflow.com/questions/40245442
复制相似问题