压缩/flate | compress/flate
Package 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,最终将压缩形式的数据写入其底层写入器。