非常教程

Go参考手册

压缩 | compress

压缩/flate | compress/flate

  • import "compress/flate"
  • 概述
  • 索引
  • 示例

概述

Package flate 实现了 RFC 1951 中描述的 DEFLATE 压缩数据格式. gzip 和 zlib 包实现了对基于 DEFLATE 的文件格式的访问。

示例(词典)

预设词典可用于提高压缩比。使用字典的缺点是压缩器和解压缩器必须事先同意使用什么字典。

package main

import (
	"bytes"
	"compress/flate"
	"fmt"
	"io"
	"log"
	"os"
	"strings"
)

func main() {
	// 字典是一串字节。 压缩一些输入数据时,
	// 压缩器将尝试用找到的匹配替换子串
	// 在字典里。因此,字典应该只包含子字符串
	// 预计会在实际的数据流中找到。
	const dict = `<?xml version="1.0"?>` + `<book>` + `<data>` + `<meta name="` + `" content="`

	// 要压缩的数据应该(但不是必需的)包含频繁的数据
	// 子字符串匹配字典中的字符串。
	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

	// 使用特制字典压缩数据。
	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)
	}

	// 解压缩器必须使用与压缩器相同的字典。
	// 否则,输入可能显示为损坏。
	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()

	// 使用'#'替代字典中的所有字节以直观地显示
	// 演示使用预设词典的大致效果。
	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)
	}

}

示例(重置)

在性能至关重要的应用中,Reset 可以用来丢弃当前的压缩器或解压缩器状态,并利用先前分配的内存快速重新初始化它们。

package main

import (
	"bytes"
	"compress/flate"
	"io"
	"log"
	"os"
	"strings"
)

func main() {
	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()

		// 重置压缩器并从某些输入流编码。
		zw.Reset(&b)
		if _, err := io.CopyBuffer(zw, &r, buf); err != nil {
			log.Fatal(err)
		}
		if err := zw.Close(); err != nil {
			log.Fatal(err)
		}

		// 重置解压缩器并解码为某个输出流。
		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)
		}
	}

}

示例(同步)

DEFLATE 适用于通过网络传输压缩数据。

package main

import (
	"compress/flate"
	"fmt"
	"io"
	"log"
	"strings"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	defer wg.Wait()

	// 使用io.Pipe来模拟网络连接。
	// 真正的网络应用程序应小心妥善关闭
	// 底层连接。
	rp, wp := io.Pipe()

	// 启动一个 goroutine 来充当发射器。
	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...") {
			// 我们使用一个简单的成帧格式,其中第一个字节是
			// 消息长度,跟随消息本身。
			b[0] = uint8(copy(b[1:], m))

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

			// 刷新确保接收器可以读取迄今为止发送的所有数据。
			if err := zw.Flush(); err != nil {
				log.Fatal(err)
			}
		}

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

	// 开始一个 goroutine 充当接收者。
	wg.Add(1)
	go func() {
		defer wg.Done()

		zr := flate.NewReader(rp)

		b := make([]byte, 256)
		for {
			// 阅读消息长度。
			// 这是保证返回每个相应的
			// (Flush)冲洗并(Close)关闭发射器侧。
			if _, err := io.ReadFull(zr, b[:1]); err != nil {
				if err == io.EOF {
					break // 发射机关闭了流
				}
				log.Fatal(err)
			}

			// 阅读消息内容。
			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)
		}
	}()

}

索引

  • Constants(常量)
  • func NewReader(r io.Reader) io.ReadCloser
  • func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser
  • type CorruptInputError
  • func (e CorruptInputError) Error() string
  • type InternalError
  • func (e InternalError) Error() string
  • type ReadError
  • func (e *ReadError) Error() string
  • type Reader
  • type Resetter
  • type WriteError
  • func (e *WriteError) Error() string
  • type 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)

示例

Package (Dictionary) Package (Reset) Package (Synchronization)

文件包

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 禁用 Lempel-Ziv 匹配搜索并仅执行 Huffman
        // 熵编码。 此模式在压缩具有的数据时非常有用
        // 已经使用LZ样式算法压缩(例如Snappy或LZ4)
        // 缺少熵编码器。 当压缩增益达到时
        // 输入流中的某些字节比其他字节更频繁地出现。
        //
        // 请注意,HuffmanOnly会生成一个压缩输出
        // 符合RFC 1951。 也就是说,任何有效的DEFLATE解压缩器都会
        // 继续能够解压缩此输出。
        HuffmanOnly = -2
)

func NewReader(查看源代码)

func NewReader(r io.Reader) io.ReadCloser

NewReader 返回一个新的 ReadCloser,可用于读取r的未压缩版本。如果r不执行 io.ByteReader,则解压缩程序可能从r读取比所需更多的数据。完成阅读时,调用者有责任在ReadCloser上调用 Close。

NewReader 返回的 ReadCloser 也实现了Resetter。

func NewReaderDict(查看源代码)

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

NewReaderDict 与 NewReader类似,但用预设字典初始化阅读器。返回的Reader的行为就像未压缩的数据流以已经读取的给定字典开始一样。NewReaderDict 通常用于读取由NewWriterDict 压缩的数据。

NewReader 返回的 ReadCloser 同样实现了 Resetter。

type CorruptInputError(查看源代码)

CorruptInputError 报告给定偏移处存在损坏的输入。

type CorruptInputError int64

func (CorruptInputError) Error(查看源代码)

func (e CorruptInputError) Error() string

type InternalError(查看源代码)

InternalError 在 flate 代码本身中报告错误。

type InternalError string

func (InternalError) Error(查看源代码)

func (e InternalError) Error() string

type ReadError(查看源代码)

ReadError 报告读取输入时遇到的错误。

已弃用:不再返回。

type ReadError struct {
        Offset int64 // 发生错误的字节偏移量
        Err    error // 底层Read返回的错误

func (*ReadError) Error(查看源代码)

func (e *ReadError) Error() string

type Reader(查看源代码)

NewReader 所需的实际读取界面。如果传入的 io.Reader 不具有ReadByte,则 NewReader 将引入它自己的缓冲区。

type Reader interface {
        io.Reader
        io.ByteReader
}

type Resetter(查看源代码)

Resetter 重置由 NewReader 或 NewReaderDict 返回的 ReadCloser 以切换到新的底层 Reader。这允许重新使用 ReadCloser 而不是分配一个新的。

type Resetter interface {
        // 重置会丢弃所有缓冲的数据并重置Resetter(就像它之前那样)
        // 最初用给定的读者初始化。
        Reset(r io.Reader, dict []byte) error
}

type WriteError(查看源代码)

WriteError 报告写入输出时遇到的错误。

已弃用:不再返回。

type WriteError struct {
        Offset int64 // 发生错误的字节偏移量
        Err    error // 底层Write返回的错误
}

func (*WriteError) Error(查看源代码)

func (e *WriteError) Error() string

type Writer(查看源代码)

Writer 将写入数据的数据写入底层写入器(请参阅NewWriter)。

type Writer struct {
        // 包含已过滤或未导出的字段
}

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)仅使用霍夫曼压缩,它为所有类型的输入提供非常快速的压缩,但会牺牲相当大的压缩效率。

如果级别在-2,9范围内,则返回的错误将为零。否则,返回的错误将不为零。

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

关闭刷新并关闭 写入器(writer)。

func (*Writer) Flush(查看源代码)

func (w *Writer) Flush() error

刷新将任何未决数据刷新到底层写入器(underlying writer)。它主要用于压缩网络协议,以确保远程读取器有足够的数据来重建数据包。在数据写入之前,刷新不会返回。在没有待处理数据时调用 Flush 仍然会导致 Writer 发出至少4个字节的同步标记。如果底层编写器返回错误,Flush 将返回该错误。

在 zlib 库的术语中,Flush 等价于 Z_SYNC_FLUSH。

func (*Writer) Reset(查看源代码)

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

重置放弃 writer 的状态,并使其等同于使用dst和w的级别和字典调用 NewWriter 或 NewWriterDict 的结果。

func (*Writer) Write(查看源代码)

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

写入数据写入 w,最终将压缩形式的数据写入其底层写入器。

Go

Go 是一种编译型语言,它结合了解释型语言的游刃有余,动态类型语言的开发效率,以及静态类型的安全性。它也打算成为现代的,支持网络与多核计算的语言。要满足这些目标,需要解决一些语言上的问题:一个富有表达能力但轻量级的类型系统,并发与垃圾回收机制,严格的依赖规范等等。这些无法通过库或工具解决好,因此Go也就应运而生了。

主页 https://golang.org/
源码 https://go.googlesource.com/go
发布版本 1.9.2

Go目录

1.档案 | archive
2.缓冲区 | bufio
3.内置 | builtin
4.字节 | bytes
5.压缩 | compress
6.容器 | container
7.上下文 | context
8.加密 | crypto
9.数据库 | database
10.调试 | debug
11.编码 | encoding
12.错误 | errors
13. expvar
14.flag
15. fmt
16. go
17.散列 | hash
18.html
19.图像 | image
20.索引 | index
21.io
22.日志 | log
23.数学 | math
24. math/big
25.math/bits
26.math/cmplx
27.math/rand
28.拟态 | mime
29.net
30.net/http
31. net/mail
32. net/rpc
33.net/smtp
34. net/textproto
35. net/url
36.os
37.路径 | path
38.插件 | plugin
39.反射 | reflect
40.正则表达式 | regexp
41.运行时 | runtime
42.排序算法 | sort
43.转换 | strconv
44.字符串 | strings
45.同步 | sync
46.系统调用 | syscall
47.测试 | testing
48.文本 | text
49.时间戳 | time
50.unicode
51.不安全性 | unsafe
52.Go 语言数据类型
53.Go 语言基础语法
54.Go 语言结构
55.Go 语言 select 语句
56.Go 语言 switch 语句
57.Go 语言 if 语句嵌套
58.Go 语言 if…else 语句
59.Go 语言 if 语句
60.Go 语言运算符
61.Go 语言常量
62.Go 语言函数闭包
63.Go 语言函数作为实参
64.Go 语言函数引用传递值
65.Go 语言函数值传递值
66.Go 语言函数
67.Go 语言 goto 语句
68.Go 语言 continue 语句
69.Go 语言 break 语句
70.Go 语言循环嵌套
71.Go 语言 for 循环
72.Go 语言结构体
73.Go 语言指针作为函数参数
74.Go 语言指向指针的指针
75.Go 语言指针数组
76.Go 语言指针
77.Go 语言向函数传递数组
78.Go 语言多维数组
79.Go 语言变量作用域
80.Go 语言函数方法
81.Go 错误处理
82.Go 语言接口
83.Go 语言类型转换
84.Go 语言递归函数
85.Go 语言Map(集合)
86.Go 语言范围(Range)
87.Go 语言切片(Slice)
88.Go 并发
89.Go fmt.Sprintf 格式化字符串