flate

package
v1.22.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 26, 2024 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package flateは、DEFLATE圧縮データ形式を実装しています。RFC 1951で説明されています。 gzipとzlibパッケージは、DEFLATEベースのファイル形式へのアクセスを実装しています。

Example (Dictionary)

あらかじめ設定された辞書を使用すると、圧縮率を改善することができます。 辞書を使用する際の難点は、圧縮機と展開機が事前に使用する辞書について合意する必要があるということです。

package main

import (
	"github.com/shogo82148/std/bytes"
	"github.com/shogo82148/std/compress/flate"
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/io"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/os"
	"github.com/shogo82148/std/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)
	}

}
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"/#
	######...</#####
</#####
Example (Reset)

パフォーマンスの重要なアプリケーションでは、Reset を使用して現在の圧縮器または伸張器の状態を破棄し、 以前に割り当てられたメモリを活用してそれらを迅速に再初期化することができます。

package main

import (
	"github.com/shogo82148/std/bytes"
	"github.com/shogo82148/std/compress/flate"
	"github.com/shogo82148/std/io"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/os"
	"github.com/shogo82148/std/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)
		}
	}

}
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.
Example (Synchronization)

DEFLATEはネットワーク上で圧縮データを送信するのに適しています。

package main

import (
	"github.com/shogo82148/std/compress/flate"
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/io"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/strings"
	"github.com/shogo82148/std/sync"
)

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

	// io.Pipeを使用してネットワーク接続をシミュレートします。
	// 実際のネットワークアプリケーションでは、基礎となる接続を適切に閉じる必要があります。
	rp, wp := io.Pipe()

	// 送信機能として機能するために、ゴールーチンを開始します。
	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)
			}

			// Flushは、受信者がこれまでに送信されたすべてのデータを読み取ることができることを保証します。
			if err := zw.Flush(); err != nil {
				log.Fatal(err)
			}
		}

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

	// 受信者として動作するゴルーチンを開始する。
	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)
		}
	}()

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

Index

Examples

Constants

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

	// HuffmanOnlyは、Lempel-Zivマッチ検索を無効化し、Huffmanエントロピー符号化のみを実行します。このモードは、すでにLZスタイルのアルゴリズム(例:SnappyやLZ4)で圧縮されたデータを圧縮する際に便利ですが、それにはエントロピー符号化が欠けています。特定のバイトが入力ストリームで他のバイトよりも頻繁に発生する場合、圧縮率が向上します。
	// HuffmanOnlyは、圧縮された出力をRFC 1951に準拠して生成します。つまり、有効なDEFLATEデコンプレッサーは、この出力を引き続き解凍できるようになります。
	HuffmanOnly = -2
)

Variables

This section is empty.

Functions

func NewReader

func NewReader(r io.Reader) io.ReadCloser

NewReader returns a new ReadCloser that can be used to read the uncompressed version of r. If r does not also implement io.ByteReader, the decompressor may read more data than necessary from r. The reader returns io.EOF after the final block in the DEFLATE stream has been encountered. Any trailing data after the final block is ignored.

NewReaderによって返される io.ReadCloser は、 Resetter も実装しています。

func NewReaderDict

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

NewReaderDictは NewReader と同じようにリーダーを初期化しますが、 事前に設定された辞書でリーダーを初期化します。 返されたリーダーは、与えられた辞書で圧縮解除されたデータストリームが開始されたかのように振る舞います。 この辞書は既に読み取られています。通常、NewWriterDictで圧縮されたデータを読み込むためにNewReaderDictが使用されます。

NewReaderによって返されたReadCloserは Resetter も実装しています。

Types

type CorruptInputError

type CorruptInputError int64

CorruptInputError は指定されたオフセットで破損した入力の存在を報告します。

func (CorruptInputError) Error

func (e CorruptInputError) Error() string

type InternalError

type InternalError string

InternalErrorはflateコード自体のエラーを報告します。

func (InternalError) Error

func (e InternalError) Error() string

type ReadError deprecated

type ReadError struct {
	Offset int64
	Err    error
}

ReadErrorは、入力を読み取る中で遭遇したエラーを報告します。

Deprecated: もはや返されません。

func (*ReadError) Error

func (e *ReadError) Error() string

type Reader

type Reader interface {
	io.Reader
	io.ByteReader
}

NewReader で必要とされる実際の読み取りインターフェース。 渡された io.Reader が ReadByte も持っていない場合、 NewReader は自身のバッファリングを導入します。

type Resetter added in v1.4.0

type Resetter interface {
	Reset(r io.Reader, dict []byte) error
}

Resetterは NewReader または NewReaderDict が返すReadCloserをリセットし、新しい基になる Reader に切り替えます。これにより、新しいものを割り当てる代わりにReadCloserを再利用することができます。

type WriteError deprecated

type WriteError struct {
	Offset int64
	Err    error
}

WriteErrorは出力の書き込み中に遭遇したエラーを報告します。

Deprecated: もう返されません。

func (*WriteError) Error

func (e *WriteError) Error() string

type Writer

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

Writerは、書き込まれたデータを受け取り、そのデータの圧縮された形式を基になるWriterに書き込む。 (NewWriter を参照してください)。

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) は Huffman 圧縮のみを使用し、全ての入力の圧縮を非常に高速化しますが、 圧縮効率を犠牲にします。

もし 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 added in v1.2.0

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

Resetは、ライターの状態を破棄し、dstとwのレベルと辞書を使用して NewWriter または NewWriterDict が呼び出された結果と同じ状態にします。

func (*Writer) Write

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

Writeは、wにデータを書き込み、その後データの圧縮形式を基になるライターに書き込みます。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL