Spec-Zone.ru › Go

Пакет flate

  • import "compress/flate"
  • Обзор
  • Индекс
  • Примеры

Обзор

Пакет flate реализует формат сжатия DEFLATE, описанный в RFC 1951. Пакеты gzip и zlib реализуют доступ к основанным на DEFLATE форматам файлов.

Пример (Словарь)

Предварительно заданный словарь можно использовать для повышения коэффициента сжатия. Недостатком использования словаря является то, что сжимающий и распаковывающий модули должны заранее договориться о том, какой словарь использовать.

Код:

// The dictionary is a string of bytes. When compressing some input data,
// the compressor will attempt to substitute substrings with matches found
// in the dictionary. As such, the dictionary should only contain substrings
// that are expected to be found in the actual data stream.
const dict = `<?xml version="1.0"?>` + `<book>` + `<data>` + `<meta name="` + `" content="`

// The data to compress should (but is not required to) contain frequent
// substrings that match those in the dictionary.
const data = `<?xml version="1.0"?>
<book>
    <meta name="title" content="The Go Programming Language"/>
    <meta name="authors" content="Alan Donovan and Brian Kernighan"/>
    <meta name="published" content="2015-10-26"/>
    <meta name="isbn" content="978-0134190440"/>
    <data>...</data>
</book>
`

var b bytes.Buffer

// Compress the data using the specially crafted dictionary.
zw, err := flate.NewWriterDict(&b, flate.DefaultCompression, []byte(dict))
if err != nil {
    log.Fatal(err)
}
if _, err := io.Copy(zw, strings.NewReader(data)); err != nil {
    log.Fatal(err)
}
if err := zw.Close(); err != nil {
    log.Fatal(err)
}

// The decompressor must use the same dictionary as the compressor.
// Otherwise, the input may appear as corrupted.
fmt.Println("Decompressed output using the dictionary:")
zr := flate.NewReaderDict(bytes.NewReader(b.Bytes()), []byte(dict))
if _, err := io.Copy(os.Stdout, zr); err != nil {
    log.Fatal(err)
}
if err := zr.Close(); err != nil {
    log.Fatal(err)
}

fmt.Println()

// Substitute all of the bytes in the dictionary with a '#' to visually
// demonstrate the approximate effectiveness of using a preset dictionary.
fmt.Println("Substrings matched by the dictionary are marked with #:")
hashDict := []byte(dict)
for i := range hashDict {
    hashDict[i] = '#'
}
zr = flate.NewReaderDict(&b, hashDict)
if _, err := io.Copy(os.Stdout, zr); err != nil {
    log.Fatal(err)
}
if err := zr.Close(); err != nil {
    log.Fatal(err)
}

Вывод:

Decompressed output using the dictionary:
<?xml version="1.0"?>
<book>
	<meta name="title" content="The Go Programming Language"/>
	<meta name="authors" content="Alan Donovan and Brian Kernighan"/>
	<meta name="published" content="2015-10-26"/>
	<meta name="isbn" content="978-0134190440"/>
	<data>...</data>
</book>

Substrings matched by the dictionary are marked with #:
#####################
######
	############title###########The Go Programming Language"/#
	############authors###########Alan Donovan and Brian Kernighan"/#
	############published###########2015-10-26"/#
	############isbn###########978-0134190440"/#
	######...</#####
</#####

Пример (Сброс)

В приложениях, критичных к производительности, можно использовать сброс, чтобы быстро сбросить текущее состояние сжимающего или распаковывающего модуля и повторно инициализировать их, используя ранее выделенную память.

Код:

proverbs := []string{
    "Don't communicate by sharing memory, share memory by communicating.\n",
    "Concurrency is not parallelism.\n",
    "The bigger the interface, the weaker the abstraction.\n",
    "Documentation is for users.\n",
}

var r strings.Reader
var b bytes.Buffer
buf := make([]byte, 32<<10)

zw, err := flate.NewWriter(nil, flate.DefaultCompression)
if err != nil {
    log.Fatal(err)
}
zr := flate.NewReader(nil)

for _, s := range proverbs {
    r.Reset(s)
    b.Reset()

    // Reset the compressor and encode from some input stream.
    zw.Reset(&b)
    if _, err := io.CopyBuffer(zw, &r, buf); err != nil {
        log.Fatal(err)
    }
    if err := zw.Close(); err != nil {
        log.Fatal(err)
    }

    // Reset the decompressor and decode to some output stream.
    if err := zr.(flate.Resetter).Reset(&b, nil); err != nil {
        log.Fatal(err)
    }
    if _, err := io.CopyBuffer(os.Stdout, zr, buf); err != nil {
        log.Fatal(err)
    }
    if err := zr.Close(); err != nil {
        log.Fatal(err)
    }
}

Вывод:

Don't communicate by sharing memory, share memory by communicating.
Concurrency is not parallelism.
The bigger the interface, the weaker the abstraction.
Documentation is for users.

Пример (Синхронизация)

DEFLATE подходит для передачи сжатых данных по сети.

Код:

var wg sync.WaitGroup
defer wg.Wait()

// Use io.Pipe to simulate a network connection.
// A real network application should take care to properly close the
// underlying connection.
rp, wp := io.Pipe()

// Start a goroutine to act as the transmitter.
wg.Add(1)
go func() {
    defer wg.Done()

    zw, err := flate.NewWriter(wp, flate.BestSpeed)
    if err != nil {
        log.Fatal(err)
    }

    b := make([]byte, 256)
    for _, m := range strings.Fields("A long time ago in a galaxy far, far away...") {
        // We use a simple framing format where the first byte is the
        // message length, followed the message itself.
        b[0] = uint8(copy(b[1:], m))

        if _, err := zw.Write(b[:1+len(m)]); err != nil {
            log.Fatal(err)
        }

        // Flush ensures that the receiver can read all data sent so far.
        if err := zw.Flush(); err != nil {
            log.Fatal(err)
        }
    }

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

// Start a goroutine to act as the receiver.
wg.Add(1)
go func() {
    defer wg.Done()

    zr := flate.NewReader(rp)

    b := make([]byte, 256)
    for {
        // Read the message length.
        // This is guaranteed to return for every corresponding
        // Flush and Close on the transmitter side.
        if _, err := io.ReadFull(zr, b[:1]); err != nil {
            if err == io.EOF {
                break // The transmitter closed the stream
            }
            log.Fatal(err)
        }

        // Read the message content.
        n := int(b[0])
        if _, err := io.ReadFull(zr, b[:n]); err != nil {
            log.Fatal(err)
        }

        fmt.Printf("Received %d bytes: %s\n", n, b[:n])
    }
    fmt.Println()

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

Вывод:

Received 1 bytes: A
Received 4 bytes: long
Received 4 bytes: time
Received 3 bytes: ago
Received 2 bytes: in
Received 1 bytes: a
Received 6 bytes: galaxy
Received 4 bytes: far,
Received 3 bytes: far
Received 7 bytes: away...

Индекс

  • Константы
  • func NewReader(r io.Reader) io.ReadCloser
  • func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser
  • тип CorruptInputError
  • func (e CorruptInputError) Error() string
  • тип InternalError
  • func (e InternalError) Error() string
  • тип ReadError
  • func (e *ReadError) Error() string
  • тип Reader
  • тип Resetter
  • тип WriteError
  • func (e *WriteError) Error() string
  • тип Writer
  • func NewWriter(w io.Writer, level int) (*Writer, error)
  • func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error)
  • func (w *Writer) Close() error
  • func (w *Writer) Flush() error
  • func (w *Writer) Reset(dst io.Writer)
  • func (w *Writer) Write(data []byte) (n int, err error)

Примеры

Пакет (Словарь)
Пакет (Сброс)
Пакет (Синхронизация)

Файлы пакета

deflate.go deflatefast.go dict_decoder.go huffman_bit_writer.go huffman_code.go inflate.go token.go

Константы

const (
    NoCompression      = 0
    BestSpeed          = 1
    BestCompression    = 9
    DefaultCompression = -1

    // HuffmanOnly disables Lempel-Ziv match searching and only performs Huffman
    // entropy encoding. This mode is useful in compressing data that has
    // already been compressed with an LZ style algorithm (e.g. Snappy or LZ4)
    // that lacks an entropy encoder. Compression gains are achieved when
    // certain bytes in the input stream occur more frequently than others.
    //
    // Note that HuffmanOnly produces a compressed output that is
    // RFC 1951 compliant. That is, any valid DEFLATE decompressor will
    // continue to be able to decompress this output.
    HuffmanOnly = -2
)

func NewReader

func NewReader(r io.Reader) io.ReadCloser

NewReader возвращает новый ReadCloser, который можно использовать для чтения несжатой версии r. Если r также не реализует io.ByteReader, распаковыватель может прочитать больше данных из r, чем необходимо. Чтец возвращает io.EOF после того, как был встречен последний блок в потоке DEFLATE. Любые данные, оставшиеся после последнего блока, игнорируются.

ReadCloser, возвращаемый NewReader, также реализует Resetter.

func NewReaderDict

func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser

NewReaderDict похож на NewReader, но инициализирует чтец с предварительно заданным словарем. Возвращаемый Reader ведет себя так, как если бы поток несжатых данных начинался с данного словаря, который уже был прочитан. NewReaderDict обычно используется для чтения данных, сжатых с помощью NewWriterDict.

ReadCloser, возвращаемый NewReaderDict, также реализует Resetter.

тип CorruptInputError

CorruptInputError сообщает о наличии поврежденного входного потока в заданном смещении.

type CorruptInputError int64

func (CorruptInputError) Error

func (e CorruptInputError) Error() string

тип InternalError

InternalError сообщает об ошибке в самом коде flate.

type InternalError string

func (InternalError) Error

func (e InternalError) Error() string

тип ReadError

ReadError сообщает об ошибке, возникшей при чтении входных данных.

Устаревшее: больше не возвращается.

type ReadError struct {
    Offset int64 // byte offset where error occurred
    Err    error // error returned by underlying Read
}

func (*ReadError) Error

func (e *ReadError) Error() string

тип Reader

Фактический интерфейс чтения, необходимый для NewReader. Если переданный io.Reader также не имеет ReadByte, NewReader добавит свою собственную буферизацию.

type Reader interface {
    io.Reader
    io.ByteReader
}

тип Resetter 1.4

Resetter сбрасывает ReadCloser, возвращаемый NewReader или NewReaderDict, чтобы переключиться на новый базовый Reader. Это позволяет повторно использовать ReadCloser вместо выделения нового.

type Resetter interface {
    // Reset discards any buffered data and resets the Resetter as if it was
    // newly initialized with the given reader.
    Reset(r io.Reader, dict []byte) error
}

тип WriteError

WriteError сообщает об ошибке, возникшей при записи выходных данных.

Устаревшее: больше не возвращается.

type WriteError struct {
    Offset int64 // byte offset where error occurred
    Err    error // error returned by underlying Write
}

func (*WriteError) Error

func (e *WriteError) Error() string

тип Writer

Writer принимает данные, записанные в него, и записывает сжатую форму этих данных в базовый писатель (см. NewWriter).

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

func NewWriter

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

NewWriter возвращает новый Writer, сжимающий данные на заданном уровне. Следуя zlib, уровни находятся в диапазоне от 1 (BestSpeed) до 9 (BestCompression); более высокие уровни обычно работают медленнее, но сжимают больше. Уровень 0 (NoCompression) не пытается произвести сжатие; он только добавляет необходимую структуру DEFLATE. Уровень -1 (DefaultCompression) использует уровень сжатия по умолчанию. Уровень -2 (HuffmanOnly) будет использовать только сжатие Хаффмана, обеспечивая очень быстрое сжатие для всех типов входных данных, но жертвуя значительной эффективностью сжатия.

Если level находится в диапазоне [-2, 9], то возвращаемая ошибка будет nil. В противном случае возвращаемая ошибка будет не nil.

func NewWriterDict

func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error)

NewWriterDict похож на NewWriter, но инициализирует новый Writer с предварительно заданным словарем. Возвращаемый Writer ведет себя так, как если бы словарь был записан в него без генерации сжатых данных. Сжатые данные, записанные в w, могут быть распакованы только Reader, инициализированным с тем же словарем.

func (*Writer) Close

func (w *Writer) Close() error

Close сбрасывает и закрывает писатель.

func (*Writer) Flush

func (w *Writer) Flush() error

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

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

func (*Writer) Reset 1.2

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

Reset отбрасывает состояние писателя и делает его эквивалентным результату NewWriter или NewWriterDict, вызываемых с dst и level и словарем w.

func (*Writer) Write

func (w *Writer) Write(data []byte) (n int, err error)

Write записывает данные в w, который в конечном итоге запишет сжатую форму данных в свой базовый писатель.

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

Spec-Zone.ru

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