1package zip 2 3import ( 4 "archive/zip" 5 "io" 6 "os" 7) 8 9// Reader provides sequential access to the contents of a zip archive. 10type Reader struct { 11 zip.Reader 12 unread []*zip.File 13 rc io.ReadCloser 14} 15 16// NewReader returns a new Reader reading from r, which is assumed to have the 17// given size in bytes. 18func NewReader(r io.ReaderAt, size int64) (*Reader, error) { 19 zr, err := zip.NewReader(r, size) 20 if err != nil { 21 return nil, err 22 } 23 return &Reader{Reader: *zr}, nil 24} 25 26// NextFile advances to the next file in the zip archive. 27func (r *Reader) NextFile() (name string, err error) { 28 // Initialize unread 29 if r.unread == nil { 30 r.unread = r.Files()[:] 31 } 32 33 // Close previous file 34 if r.rc != nil { 35 r.rc.Close() // Read-only 36 } 37 38 if len(r.unread) == 0 { 39 return "", io.EOF 40 } 41 42 // Open and return next unread 43 f := r.unread[0] 44 name, r.unread = f.Name, r.unread[1:] 45 r.rc, err = f.Open() 46 if err != nil { 47 return "", err 48 } 49 return name, nil 50} 51 52func (r *Reader) Read(p []byte) (n int, err error) { 53 return r.rc.Read(p) 54} 55 56// Files returns the full list of files in the zip archive. 57func (r *Reader) Files() []*zip.File { 58 return r.File 59} 60 61// Writer provides sequential writing of a zip archive.1 format. 62type Writer struct { 63 zip.Writer 64 w io.Writer 65} 66 67// NewWriter returns a new Writer writing to w. 68func NewWriter(w io.Writer) *Writer { 69 return &Writer{Writer: *zip.NewWriter(w)} 70} 71 72// NextFile computes and writes a header and prepares to accept the file's 73// contents. 74func (w *Writer) NextFile(name string, fi os.FileInfo) error { 75 if name == "" { 76 name = fi.Name() 77 } 78 hdr, err := zip.FileInfoHeader(fi) 79 if err != nil { 80 return err 81 } 82 hdr.Name = name 83 w.w, err = w.CreateHeader(hdr) 84 return err 85} 86 87func (w *Writer) Write(p []byte) (n int, err error) { 88 return w.w.Write(p) 89} 90