90 lines
1.8 KiB
Go
90 lines
1.8 KiB
Go
package zip
|
|
|
|
import (
|
|
"archive/zip"
|
|
"io"
|
|
"os"
|
|
)
|
|
|
|
// Reader provides sequential access to the contents of a zip archive.
|
|
type Reader struct {
|
|
zip.Reader
|
|
unread []*zip.File
|
|
rc io.ReadCloser
|
|
}
|
|
|
|
// NewReader returns a new Reader reading from r, which is assumed to have the
|
|
// given size in bytes.
|
|
func NewReader(r io.ReaderAt, size int64) (*Reader, error) {
|
|
zr, err := zip.NewReader(r, size)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Reader{Reader: *zr}, nil
|
|
}
|
|
|
|
// NextFile advances to the next file in the zip archive.
|
|
func (r *Reader) NextFile() (name string, err error) {
|
|
// Initialize unread
|
|
if r.unread == nil {
|
|
r.unread = r.Files()[:]
|
|
}
|
|
|
|
// Close previous file
|
|
if r.rc != nil {
|
|
r.rc.Close() // Read-only
|
|
}
|
|
|
|
if len(r.unread) == 0 {
|
|
return "", io.EOF
|
|
}
|
|
|
|
// Open and return next unread
|
|
f := r.unread[0]
|
|
name, r.unread = f.Name, r.unread[1:]
|
|
r.rc, err = f.Open()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return name, nil
|
|
}
|
|
|
|
func (r *Reader) Read(p []byte) (n int, err error) {
|
|
return r.rc.Read(p)
|
|
}
|
|
|
|
// Files returns the full list of files in the zip archive.
|
|
func (r *Reader) Files() []*zip.File {
|
|
return r.File
|
|
}
|
|
|
|
// Writer provides sequential writing of a zip archive.1 format.
|
|
type Writer struct {
|
|
zip.Writer
|
|
w io.Writer
|
|
}
|
|
|
|
// NewWriter returns a new Writer writing to w.
|
|
func NewWriter(w io.Writer) *Writer {
|
|
return &Writer{Writer: *zip.NewWriter(w)}
|
|
}
|
|
|
|
// NextFile computes and writes a header and prepares to accept the file's
|
|
// contents.
|
|
func (w *Writer) NextFile(name string, fi os.FileInfo) error {
|
|
if name == "" {
|
|
name = fi.Name()
|
|
}
|
|
hdr, err := zip.FileInfoHeader(fi)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
hdr.Name = name
|
|
w.w, err = w.CreateHeader(hdr)
|
|
return err
|
|
}
|
|
|
|
func (w *Writer) Write(p []byte) (n int, err error) {
|
|
return w.w.Write(p)
|
|
}
|