Пакет 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...
Индекс
Файлы пакета
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/