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
  • функция NewReader(r io.Reader) (*Reader, error)
  • функция (z *Reader) Close() error
  • функция (z *Reader) Multistream(ok bool)
  • функция (z *Reader) Read(p []byte) (n int, err error)
  • функция (z *Reader) Reset(r io.Reader) error
  • тип Writer
  • функция NewWriter(w io.Writer) *Writer
  • функция NewWriterLevel(w io.Writer, level int) (*Writer, error)
  • функция (z *Writer) Close() error
  • функция (z *Writer) Flush() error
  • функция (z *Writer) Reset(w io.Writer)
  • функция (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 и могут содержать только символы Юникода с 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
}

функция NewReader

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

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

Ответственность за вызов Close на Reader после использования лежит на вызывающей стороне.

Поля [Reader.Header] в возвращаемом Reader будут валидными.

функция (*Reader) Close

func (z *Reader) Close() error

Close закрывает Reader. Он не закрывает базовый io.Reader. Для проверки контрольной суммы GZIP читатель должен быть полностью потреблен до io.EOF.

функция (*Reader) Multistream 1.4

func (z *Reader) Multistream(ok bool)

Multistream контролирует, поддерживает ли читатель файлы multistream.

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

Вызов Multistream(false) отключает это поведение; отключение поведения может быть полезным при чтении форматов файлов, которые различают отдельные gzipped потоки данных или смешивают gzipped потоки с другими потоками данных. В этом режиме, когда Reader достигает конца потока данных, Reader.Read возвращает io.EOF. Базовый reader должен реализовывать io.ByteReader, чтобы остаться позиционированным сразу после gzipped потока. Чтобы начать следующий поток, вызовите 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

функция (*Reader) Read

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

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

функция (*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
}

функция NewWriter

func NewWriter(w io.Writer) *Writer

NewWriter возвращает новый Writer. Записи в возвращаемый writer сжимаются и записываются в w.

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

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

функция NewWriterLevel

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

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

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

функция (*Writer) Close

func (z *Writer) Close() error

Close закрывает Writer, сбрасывая все не записанные данные в базовый io.Writer и записывая подпись GZIP. Он не закрывает базовый io.Writer.

функция (*Writer) Flush 1.1

func (z *Writer) Flush() error

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

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

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

функция (*Writer) Reset 1.2

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

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

функция (*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