1
0
mirror of https://github.com/golang/go synced 2024-11-25 08:07:57 -07:00

archive/zip: add new type ReadCloser, make OpenReader return it.

Fixes #1678.

R=adg, rsc
CC=golang-dev
https://golang.org/cl/4372047
This commit is contained in:
Dmitry Chestnykh 2011-04-10 11:23:23 +10:00 committed by Andrew Gerrand
parent 1bc84b7e18
commit 1b7142d157
2 changed files with 40 additions and 12 deletions

View File

@ -35,6 +35,11 @@ type Reader struct {
Comment string Comment string
} }
type ReadCloser struct {
f *os.File
Reader
}
type File struct { type File struct {
FileHeader FileHeader
zipr io.ReaderAt zipr io.ReaderAt
@ -47,43 +52,60 @@ func (f *File) hasDataDescriptor() bool {
return f.Flags&0x8 != 0 return f.Flags&0x8 != 0
} }
// OpenReader will open the Zip file specified by name and return a Reader. // OpenReader will open the Zip file specified by name and return a ReaderCloser.
func OpenReader(name string) (*Reader, os.Error) { func OpenReader(name string) (*ReadCloser, os.Error) {
f, err := os.Open(name) f, err := os.Open(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
fi, err := f.Stat() fi, err := f.Stat()
if err != nil { if err != nil {
f.Close()
return nil, err return nil, err
} }
return NewReader(f, fi.Size) r := new(ReadCloser)
if err := r.init(f, fi.Size); err != nil {
f.Close()
return nil, err
}
return r, nil
} }
// NewReader returns a new Reader reading from r, which is assumed to // NewReader returns a new Reader reading from r, which is assumed to
// have the given size in bytes. // have the given size in bytes.
func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) { func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) {
zr := new(Reader)
if err := zr.init(r, size); err != nil {
return nil, err
}
return zr, nil
}
func (z *Reader) init(r io.ReaderAt, size int64) os.Error {
end, err := readDirectoryEnd(r, size) end, err := readDirectoryEnd(r, size)
if err != nil { if err != nil {
return nil, err return err
}
z := &Reader{
r: r,
File: make([]*File, end.directoryRecords),
Comment: end.comment,
} }
z.r = r
z.File = make([]*File, end.directoryRecords)
z.Comment = end.comment
rs := io.NewSectionReader(r, 0, size) rs := io.NewSectionReader(r, 0, size)
if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil { if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil {
return nil, err return err
} }
buf := bufio.NewReader(rs) buf := bufio.NewReader(rs)
for i := range z.File { for i := range z.File {
z.File[i] = &File{zipr: r, zipsize: size} z.File[i] = &File{zipr: r, zipsize: size}
if err := readDirectoryHeader(z.File[i], buf); err != nil { if err := readDirectoryHeader(z.File[i], buf); err != nil {
return nil, err return err
} }
} }
return z, nil return nil
}
// Close closes the Zip file, rendering it unusable for I/O.
func (rc *ReadCloser) Close() os.Error {
return rc.f.Close()
} }
// Open returns a ReadCloser that provides access to the File's contents. // Open returns a ReadCloser that provides access to the File's contents.

View File

@ -76,6 +76,12 @@ func readTestZip(t *testing.T, zt ZipTest) {
return return
} }
// bail if file is not zip
if err == FormatError {
return
}
defer z.Close()
// bail here if no Files expected to be tested // bail here if no Files expected to be tested
// (there may actually be files in the zip, but we don't care) // (there may actually be files in the zip, but we don't care)
if zt.File == nil { if zt.File == nil {