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:
parent
1bc84b7e18
commit
1b7142d157
@ -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.
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user