zipstream

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 26, 2026 License: GPL-3.0 Imports: 13 Imported by: 1

README

zipstream

Package zipstream is an on-the-fly extractor/reader for zip archive similar as Java's java.util.zip.ZipInputStream, there is no need to provide io.ReaderAt and archive size, that is, just only one io.Reader parameter.

Implementation

Most code in this package is directly copied from Golang standard archive/zip library, you can read the ZIP specification from here.

Usage

go get github.com/zhyee/zipstream

Examples

package main

import (
	"io"
	"log"
	"net/http"

	"github.com/zhyee/zipstream"
)

func main() {

	resp, err := http.Get("https://github.com/golang/go/archive/refs/tags/go1.16.10.zip")
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	zr := zipstream.NewReader(resp.Body)

	for zr.Next() {
		e, err := zr.Entry()
		if err != nil {
			log.Fatalf("unable to get next entry: %s", err)
		}

		log.Println("entry name: ", e.Name)
		log.Println("entry comment: ", e.Comment)
		log.Println("entry reader version: ", e.ReaderVersion)
		log.Println("entry modify time: ", e.Modified)
		log.Println("entry compressed size: ", e.CompressedSize64)
		log.Println("entry uncompressed size: ", e.UncompressedSize64)
		log.Println("entry is a dir: ", e.IsDir())

		if !e.IsDir() {
			rc, err := e.Open()
			if err != nil {
				log.Fatalf("unable to open zip file: %s", err)
			}
			content, err := io.ReadAll(rc)
			if err != nil {
				log.Fatalf("read zip file content fail: %s", err)
			}

			log.Println("file length:", len(content))

			if uint64(len(content)) != e.UncompressedSize64 {
				log.Fatalf("read zip file length not equal with UncompressedSize64")
			}
			if err := rc.Close(); err != nil {
				log.Fatalf("close zip entry reader fail: %s", err)
			}
		}
	}
	if err = zr.Err(); err != nil {
		log.Fatalf("encounter error: %v", err)
    }
}

Limitations

  • The entry's size, compressed size, CRC32 may be unknown until the file has been fully read, due to the presence of a data descriptor.
  • Repeatable read is not supported, each file in the zip archive can be read only once per Reader instance.
  • Some central directory header fields are unresolved — including version made by, internal file attributes, external file attributes and relative offset of local header. Additionally, certain other central directory header fields (e.g., extra field) may differ from their counterparts in the local file header.
  • Concurrent reading of multiple files is not supported.

Documentation

Index

Constants

View Source
const (
	Zip64ExtraID       = 0x0001 // Zip64 extended information
	NtfsExtraID        = 0x000a // NTFS
	UnixExtraID        = 0x000d // UNIX
	ExtTimeExtraID     = 0x5455 // Extended timestamp
	InfoZipUnixExtraID = 0x5855 // Info-ZIP Unix extension

)

Variables

This section is empty.

Functions

func MSDosTimeToTime

func MSDosTimeToTime(dosDate, dosTime uint16) time.Time

Types

type Entry

type Entry struct {
	zip.FileHeader
	// contains filtered or unexported fields
}

func (*Entry) IsDir

func (e *Entry) IsDir() bool

IsDir just simply verify whether the filename ends with a forward slash "/".

func (*Entry) Open

func (e *Entry) Open() (io.ReadCloser, error)

func (*Entry) OpenRaw

func (e *Entry) OpenRaw() (io.ReadCloser, error)

OpenRaw read the entry's original compressed(or stored) data, you must be aware that this method may be significantly slower than the same one in standard package archive/zip, especially handle the entry with a data descriptor because we must decompress all the file to determine its EOF position. See the Unit Test case BenchmarkOpenRaw for details.

func (*Entry) Skip

func (e *Entry) Skip() error

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

func NewReader

func NewReader(r io.Reader) *Reader

func (*Reader) Entry

func (z *Reader) Entry() (*Entry, error)

func (*Reader) Err

func (z *Reader) Err() error

func (*Reader) GetNextEntry

func (z *Reader) GetNextEntry() (*Entry, error)

GetNextEntry return next entry in the zip archive Deprecated, together use Next and Entry instead

func (*Reader) Next

func (z *Reader) Next() bool

Next indicates whether there is more entry can be read, You can check err to judge if there is any failure when it returns false.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL