go example_test 源码

2022-07-15 浏览 (845)

golang example_test 代码

文件路径:/src/compress/flate/example_test.go

/ 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...
}

相关信息

go 源码目录

相关文章

go deflate 源码

go deflate_test 源码

go deflatefast 源码

go dict_decoder 源码

go dict_decoder_test 源码

go flate_test 源码

go huffman_bit_writer 源码

go huffman_bit_writer_test 源码

go huffman_code 源码

go inflate 源码

^