mirror of
https://github.com/golang/go
synced 2024-11-23 15:00:03 -07:00
compress/flate: add examples
Updates #16360 Change-Id: I66ff23e0501363f58fe891d5e95806422071f93b Reviewed-on: https://go-review.googlesource.com/30162 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
2f497263e4
commit
091ba60bd8
243
src/compress/flate/example_test.go
Normal file
243
src/compress/flate/example_test.go
Normal file
@ -0,0 +1,243 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package flate_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/flate"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// In performance critical applications, Reset can be used to discard the
|
||||
// current compressor or decompressor state and reinitialize them quickly
|
||||
// by taking advantage of previously allocated memory.
|
||||
func Example_reset() {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 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.
|
||||
}
|
||||
|
||||
// A preset dictionary can be used to improve the compression ratio.
|
||||
// The downside to using a dictionary is that the compressor and decompressor
|
||||
// must agree in advance what dictionary to use.
|
||||
func Example_dictionary() {
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 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"/#
|
||||
// ######...</#####
|
||||
// </#####
|
||||
}
|
||||
|
||||
// DEFLATE is suitable for transmitting compressed data across the network.
|
||||
func Example_synchronization() {
|
||||
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)
|
||||
}
|
||||
}()
|
||||
|
||||
// Output:
|
||||
// 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...
|
||||
}
|
Loading…
Reference in New Issue
Block a user