Spec-Zone.ru › Go

Пакет gzip

  • import "compress/gzip"
  • Обзор
  • Указатель
  • Примеры

Обзор

Пакет gzip реализует чтение и запись файлов, сжатых в формате gzip, определённом в RFC 1952.

Пример (CompressingReader)

Код:

// This is an example of writing a compressing reader.
// This can be useful for an HTTP client body, as shown.

const testdata = "the data to be compressed"

// This HTTP handler is just for testing purposes.
handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
    zr, err := gzip.NewReader(req.Body)
    if err != nil {
        log.Fatal(err)
    }

    // Just output the data for the example.
    if _, err := io.Copy(os.Stdout, zr); err != nil {
        log.Fatal(err)
    }
})
ts := httptest.NewServer(handler)
defer ts.Close()

// The remainder is the example code.

// The data we want to compress, as an io.Reader
dataReader := strings.NewReader(testdata)

// bodyReader is the body of the HTTP request, as an io.Reader.
// httpWriter is the body of the HTTP request, as an io.Writer.
bodyReader, httpWriter := io.Pipe()

// Make sure that bodyReader is always closed, so that the
// goroutine below will always exit.
defer bodyReader.Close()

// gzipWriter compresses data to httpWriter.
gzipWriter := gzip.NewWriter(httpWriter)

// errch collects any errors from the writing goroutine.
errch := make(chan error, 1)

go func() {
    defer close(errch)
    sentErr := false
    sendErr := func(err error) {
        if !sentErr {
            errch <- err
            sentErr = true
        }
    }

    // Copy our data to gzipWriter, which compresses it to
    // gzipWriter, which feeds it to bodyReader.
    if _, err := io.Copy(gzipWriter, dataReader); err != nil && err != io.ErrClosedPipe {
        sendErr(err)
    }
    if err := gzipWriter.Close(); err != nil && err != io.ErrClosedPipe {
        sendErr(err)
    }
    if err := httpWriter.Close(); err != nil && err != io.ErrClosedPipe {
        sendErr(err)
    }
}()

// Send an HTTP request to the test server.
req, err := http.NewRequest("PUT", ts.URL, bodyReader)
if err != nil {
    log.Fatal(err)
}

// Note that passing req to http.Client.Do promises that it
// will close the body, in this case bodyReader.
resp, err := ts.Client().Do(req)
if err != nil {
    log.Fatal(err)
}

// Check whether there was an error compressing the data.
if err := <-errch; err != nil {
    log.Fatal(err)
}

// For this example we don't care about the response.
resp.Body.Close()

Вывод:

the data to be compressed

Пример (WriterReader)

Код:

var buf bytes.Buffer
zw := gzip.NewWriter(&buf)

// Setting the Header fields is optional.
zw.Name = "a-new-hope.txt"
zw.Comment = "an epic space opera by George Lucas"
zw.ModTime = time.Date(1977, time.May, 25, 0, 0, 0, 0, time.UTC)

_, err := zw.Write([]byte("A long time ago in a galaxy far, far away..."))
if err != nil {
    log.Fatal(err)
}

if err := zw.Close(); err != nil {
    log.Fatal(err)
}

zr, err := gzip.NewReader(&buf)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Name: %s\nComment: %s\nModTime: %s\n\n", zr.Name, zr.Comment, zr.ModTime.UTC())

if _, err := io.Copy(os.Stdout, zr); err != nil {
    log.Fatal(err)
}

if err := zr.Close(); err != nil {
    log.Fatal(err)
}

Вывод:

Name: a-new-hope.txt
Comment: an epic space opera by George Lucas
ModTime: 1977-05-25 00:00:00 +0000 UTC

A long time ago in a galaxy far, far away...

Указатель

  • Константы
  • Переменные
  • тип Header
  • тип Reader
  • func NewReader(r io.Reader) (*Reader, error)
  • func (z *Reader) Close() error
  • func (z *Reader) Multistream(ok bool)
  • func (z *Reader) Read(p []byte) (n int, err error)
  • func (z *Reader) Reset(r io.Reader) error
  • тип Writer
  • func NewWriter(w io.Writer) *Writer
  • func NewWriterLevel(w io.Writer, level int) (*Writer, error)
  • func (z *Writer) Close() error
  • func (z *Writer) Flush() error
  • func (z *Writer) Reset(w io.Writer)
  • func (z *Writer) Write(p []byte) (int, error)

Примеры

Reader.Multistream
Пакет (CompressingReader)
Пакет (WriterReader)

Файлы пакета

gunzip.go gzip.go

Константы

Эти константы скопированы из пакета flate, чтобы коду, импортирующему compress/gzip, не приходилось также импортировать compress/flate.

const (
    NoCompression      = flate.NoCompression
    BestSpeed          = flate.BestSpeed
    BestCompression    = flate.BestCompression
    DefaultCompression = flate.DefaultCompression
    HuffmanOnly        = flate.HuffmanOnly
)

Переменные

var (
    // ErrChecksum is returned when reading GZIP data that has an invalid checksum.
    ErrChecksum = errors.New("gzip: invalid checksum")
    // ErrHeader is returned when reading GZIP data that has an invalid header.
    ErrHeader = errors.New("gzip: invalid header")
)

тип Header

В файле gzip хранится заголовок с метаданными о сжатом файле. Этот заголовок представлен полями структур Writer и Reader.

Строки должны быть закодированы в UTF-8 и могут содержать только кодовые точки Unicode от U+0001 до U+00FF включительно из-за ограничений формата файла GZIP.

type Header struct {
    Comment string    // comment
    Extra   []byte    // "extra data"
    ModTime time.Time // modification time
    Name    string    // file name
    OS      byte      // operating system type
}

тип Reader

Reader — это io.Reader, чтение из которого позволяет получить несжатые данные из файла, сжатого в формате gzip.

Как правило, файл gzip может состоять из объединённых файлов gzip, каждый из которых имеет собственный заголовок. При чтении из Reader возвращается объединение несжатых данных каждого файла. В полях Reader сохраняется только первый заголовок.

В файлах gzip хранятся длина и контрольная сумма несжатых данных. Reader возвращает ошибку ErrChecksum, когда Reader.Read достигает конца несжатых данных, если длина или контрольная сумма не совпадает с ожидаемой. Клиентам следует считать данные, возвращённые Reader.Read, предварительными до получения io.EOF, обозначающего конец данных.

type Reader struct {
    Header // valid after NewReader or Reader.Reset
    // contains filtered or unexported fields
}

func NewReader

func NewReader(r io.Reader) (*Reader, error)

NewReader создаёт новый Reader для чтения из указанного объекта чтения. Если r также не реализует io.ByteReader, декомпрессор может прочитать из r больше данных, чем необходимо.

Вызывающая сторона отвечает за вызов Reader.Close после завершения работы.

Поля Reader.Header будут действительными у возвращённого Reader.

func (*Reader) Close

func (z *Reader) Close() error

Close закрывает Reader. Базовый объект чтения при этом не закрывается. Чтобы проверить контрольную сумму GZIP, необходимо полностью прочитать данные до io.EOF.

func (*Reader) Multistream 1.4

func (z *Reader) Multistream(ok bool)

Multistream определяет, поддерживает ли Reader файлы с несколькими потоками данных.

Если поддержка включена (по умолчанию), Reader ожидает, что входные данные представляют собой последовательность отдельных потоков данных gzip, каждый со своим заголовком и завершающей частью и заканчивающийся EOF. В результате объединение последовательности файлов gzip обрабатывается так же, как gzip-представление объединения этой последовательности. Это стандартное поведение средств чтения gzip.

Вызов Multistream(false) отключает это поведение; это может быть полезно при чтении форматов файлов, в которых отдельные потоки данных gzip различаются, или где потоки данных gzip смешаны с другими потоками данных. В этом режиме, когда Reader достигает конца потока данных, Reader.Read возвращает io.EOF. Чтобы оставить базовый объект чтения сразу после потока gzip, он должен реализовывать io.ByteReader. Чтобы начать чтение следующего потока, вызовите z.Reset(r), а затем z.Multistream(false). Если следующего потока нет, z.Reset(r) вернёт io.EOF.

Пример

Код:

var buf bytes.Buffer
zw := gzip.NewWriter(&buf)

var files = []struct {
    name    string
    comment string
    modTime time.Time
    data    string
}{
    {"file-1.txt", "file-header-1", time.Date(2006, time.February, 1, 3, 4, 5, 0, time.UTC), "Hello Gophers - 1"},
    {"file-2.txt", "file-header-2", time.Date(2007, time.March, 2, 4, 5, 6, 1, time.UTC), "Hello Gophers - 2"},
}

for _, file := range files {
    zw.Name = file.name
    zw.Comment = file.comment
    zw.ModTime = file.modTime

    if _, err := zw.Write([]byte(file.data)); err != nil {
        log.Fatal(err)
    }

    if err := zw.Close(); err != nil {
        log.Fatal(err)
    }

    zw.Reset(&buf)
}

zr, err := gzip.NewReader(&buf)
if err != nil {
    log.Fatal(err)
}

for {
    zr.Multistream(false)
    fmt.Printf("Name: %s\nComment: %s\nModTime: %s\n\n", zr.Name, zr.Comment, zr.ModTime.UTC())

    if _, err := io.Copy(os.Stdout, zr); err != nil {
        log.Fatal(err)
    }

    fmt.Print("\n\n")

    err = zr.Reset(&buf)
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
}

if err := zr.Close(); err != nil {
    log.Fatal(err)
}

Вывод:

Name: file-1.txt
Comment: file-header-1
ModTime: 2006-02-01 03:04:05 +0000 UTC

Hello Gophers - 1

Name: file-2.txt
Comment: file-header-2
ModTime: 2007-03-02 04:05:06 +0000 UTC

Hello Gophers - 2

func (*Reader) Read

func (z *Reader) Read(p []byte) (n int, err error)

Read реализует io.Reader, читая несжатые байты из базового объекта чтения.

func (*Reader) Reset 1.3

func (z *Reader) Reset(r io.Reader) error

Reset сбрасывает состояние Reader z и приводит его в состояние, соответствующее исходному состоянию после вызова NewReader, но для чтения из r. Это позволяет повторно использовать Reader вместо выделения нового.

тип Writer

Writer — это io.WriteCloser. Запись в Writer сжимает данные и записывает их в w.

type Writer struct {
    Header // written at first call to Write, Flush, or Close
    // contains filtered or unexported fields
}

func NewWriter

func NewWriter(w io.Writer) *Writer

NewWriter возвращает новый Writer. Запись в возвращённый объект writer сжимает данные и записывает их в w.

Вызывающая сторона отвечает за вызов Close для Writer после завершения работы. Записи могут буферизоваться и не сбрасываться до вызова Close.

Вызывающие стороны, которым нужно задать поля Writer.Header, должны сделать это до первого вызова Write, Flush или Close.

Обратите внимание: точные байты, записываемые в w, не подпадают под гарантию совместимости Go 1. Вызывающим сторонам, в том числе тестам, не следует полагаться на точное содержимое записанных байтов.

func NewWriterLevel

func NewWriterLevel(w io.Writer, level int) (*Writer, error)

NewWriterLevel аналогичен NewWriter, но позволяет задать уровень сжатия вместо использования DefaultCompression.

Уровнем сжатия может быть DefaultCompression, NoCompression, HuffmanOnly или любое целое значение от BestSpeed до BestCompression включительно. Если уровень допустим, возвращаемая ошибка будет равна nil.

Обратите внимание: точные байты, записываемые в w, не подпадают под гарантию совместимости Go 1. Вызывающим сторонам, в том числе тестам, не следует полагаться на точное содержимое записанных байтов.

func (*Writer) Close

func (z *Writer) Close() error

Close закрывает Writer, сбрасывая все незаписанные данные в базовый io.Writer и записывая завершающую часть GZIP. Базовый io.Writer при этом не закрывается.

func (*Writer) Flush 1.1

func (z *Writer) Flush() error

Flush сбрасывает все ожидающие сжатые данные в базовый объект записи.

Этот метод полезен главным образом в сетевых протоколах со сжатием, чтобы удалённый читатель получил достаточно данных для восстановления пакета. Flush не возвращает управление, пока данные не будут записаны. Если базовый объект записи возвращает ошибку, Flush возвращает эту ошибку.

В терминологии библиотеки zlib Flush эквивалентен Z_SYNC_FLUSH.

func (*Writer) Reset 1.2

func (z *Writer) Reset(w io.Writer)

Reset сбрасывает состояние Writer z и приводит его в состояние, соответствующее исходному состоянию после вызова NewWriter или NewWriterLevel, но для записи в w. Это позволяет повторно использовать Writer вместо выделения нового.

func (*Writer) Write

func (z *Writer) Write(p []byte) (int, error)

Write записывает сжатую форму p в базовый io.Writer. Сжатые байты могут не сбрасываться до закрытия Writer.

© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/compress/gzip/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API