github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/compress/flate/example_test.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package flate_test 6 7 import ( 8 "github.com/shogo82148/std/bytes" 9 "github.com/shogo82148/std/compress/flate" 10 "github.com/shogo82148/std/fmt" 11 "github.com/shogo82148/std/io" 12 "github.com/shogo82148/std/log" 13 "github.com/shogo82148/std/os" 14 "github.com/shogo82148/std/strings" 15 "github.com/shogo82148/std/sync" 16 ) 17 18 // パフォーマンスの重要なアプリケーションでは、Reset を使用して現在の圧縮器または伸張器の状態を破棄し、 19 // 以前に割り当てられたメモリを活用してそれらを迅速に再初期化することができます。 20 func Example_reset() { 21 proverbs := []string{ 22 "Don't communicate by sharing memory, share memory by communicating.\n", 23 "Concurrency is not parallelism.\n", 24 "The bigger the interface, the weaker the abstraction.\n", 25 "Documentation is for users.\n", 26 } 27 28 var r strings.Reader 29 var b bytes.Buffer 30 buf := make([]byte, 32<<10) 31 32 zw, err := flate.NewWriter(nil, flate.DefaultCompression) 33 if err != nil { 34 log.Fatal(err) 35 } 36 zr := flate.NewReader(nil) 37 38 for _, s := range proverbs { 39 r.Reset(s) 40 b.Reset() 41 42 // コンプレッサーをリセットし、入力ストリームからエンコードします。 43 zw.Reset(&b) 44 if _, err := io.CopyBuffer(zw, &r, buf); err != nil { 45 log.Fatal(err) 46 } 47 if err := zw.Close(); err != nil { 48 log.Fatal(err) 49 } 50 51 // デコンプレッサをリセットし、いくつかの出力ストリームにデコードします。 52 if err := zr.(flate.Resetter).Reset(&b, nil); err != nil { 53 log.Fatal(err) 54 } 55 if _, err := io.CopyBuffer(os.Stdout, zr, buf); err != nil { 56 log.Fatal(err) 57 } 58 if err := zr.Close(); err != nil { 59 log.Fatal(err) 60 } 61 } 62 63 // Output: 64 // Don't communicate by sharing memory, share memory by communicating. 65 // Concurrency is not parallelism. 66 // The bigger the interface, the weaker the abstraction. 67 // Documentation is for users. 68 } 69 70 // あらかじめ設定された辞書を使用すると、圧縮率を改善することができます。 71 // 辞書を使用する際の難点は、圧縮機と展開機が事前に使用する辞書について合意する必要があるということです。 72 func Example_dictionary() { 73 74 // 辞書はバイトの連続です。入力データを圧縮する際、圧縮器は辞書内で見つかった一致する部分文字列を代替しようとします。そのため、辞書には実際のデータストリームで見つかることが期待される部分文字列のみを含めるべきです。 75 const dict = `<?xml version="1.0"?>` + `<book>` + `<data>` + `<meta name="` + `" content="` 76 77 // 圧縮するデータには、辞書と一致する頻繁な(必要ではありませんが)部分文字列が含まれることが望ましいです。 78 const data = `<?xml version="1.0"?> 79 <book> 80 <meta name="title" content="The Go Programming Language"/> 81 <meta name="authors" content="Alan Donovan and Brian Kernighan"/> 82 <meta name="published" content="2015-10-26"/> 83 <meta name="isbn" content="978-0134190440"/> 84 <data>...</data> 85 </book> 86 ` 87 88 var b bytes.Buffer 89 90 // 特殊に作られた辞書を使用してデータを圧縮する。 91 zw, err := flate.NewWriterDict(&b, flate.DefaultCompression, []byte(dict)) 92 if err != nil { 93 log.Fatal(err) 94 } 95 if _, err := io.Copy(zw, strings.NewReader(data)); err != nil { 96 log.Fatal(err) 97 } 98 if err := zw.Close(); err != nil { 99 log.Fatal(err) 100 } 101 102 // 解凍プログラムは圧縮プログラムと同じ辞書を使用する必要があります。 103 // そうでないと、入力が破損しているように見えるかもしれません。 104 fmt.Println("Decompressed output using the dictionary:") 105 zr := flate.NewReaderDict(bytes.NewReader(b.Bytes()), []byte(dict)) 106 if _, err := io.Copy(os.Stdout, zr); err != nil { 107 log.Fatal(err) 108 } 109 if err := zr.Close(); err != nil { 110 log.Fatal(err) 111 } 112 113 fmt.Println() 114 115 // 辞書のすべてのバイトを '#' に置き換えて、予め設定された辞書の近似効果を視覚的に示します。 116 fmt.Println("Substrings matched by the dictionary are marked with #:") 117 hashDict := []byte(dict) 118 for i := range hashDict { 119 hashDict[i] = '#' 120 } 121 zr = flate.NewReaderDict(&b, hashDict) 122 if _, err := io.Copy(os.Stdout, zr); err != nil { 123 log.Fatal(err) 124 } 125 if err := zr.Close(); err != nil { 126 log.Fatal(err) 127 } 128 129 // Output: 130 // Decompressed output using the dictionary: 131 // <?xml version="1.0"?> 132 // <book> 133 // <meta name="title" content="The Go Programming Language"/> 134 // <meta name="authors" content="Alan Donovan and Brian Kernighan"/> 135 // <meta name="published" content="2015-10-26"/> 136 // <meta name="isbn" content="978-0134190440"/> 137 // <data>...</data> 138 // </book> 139 // 140 // Substrings matched by the dictionary are marked with #: 141 // ##################### 142 // ###### 143 // ############title###########The Go Programming Language"/# 144 // ############authors###########Alan Donovan and Brian Kernighan"/# 145 // ############published###########2015-10-26"/# 146 // ############isbn###########978-0134190440"/# 147 // ######...</##### 148 // </##### 149 } 150 151 // DEFLATEはネットワーク上で圧縮データを送信するのに適しています。 152 func Example_synchronization() { 153 var wg sync.WaitGroup 154 defer wg.Wait() 155 156 // io.Pipeを使用してネットワーク接続をシミュレートします。 157 // 実際のネットワークアプリケーションでは、基礎となる接続を適切に閉じる必要があります。 158 rp, wp := io.Pipe() 159 160 // 送信機能として機能するために、ゴールーチンを開始します。 161 wg.Add(1) 162 go func() { 163 defer wg.Done() 164 165 zw, err := flate.NewWriter(wp, flate.BestSpeed) 166 if err != nil { 167 log.Fatal(err) 168 } 169 170 b := make([]byte, 256) 171 for _, m := range strings.Fields("A long time ago in a galaxy far, far away...") { 172 173 // 最初のバイトがメッセージの長さであり、その後にメッセージ自体が続く、単純なフレーム形式を使用しています。 174 b[0] = uint8(copy(b[1:], m)) 175 176 if _, err := zw.Write(b[:1+len(m)]); err != nil { 177 log.Fatal(err) 178 } 179 180 // Flushは、受信者がこれまでに送信されたすべてのデータを読み取ることができることを保証します。 181 if err := zw.Flush(); err != nil { 182 log.Fatal(err) 183 } 184 } 185 186 if err := zw.Close(); err != nil { 187 log.Fatal(err) 188 } 189 }() 190 191 // 受信者として動作するゴルーチンを開始する。 192 wg.Add(1) 193 go func() { 194 defer wg.Done() 195 196 zr := flate.NewReader(rp) 197 198 b := make([]byte, 256) 199 for { 200 201 // メッセージの長さを読み取ります。 202 // これは送信側のFlushとCloseに対して 203 // 必ず返されることが保証されています。 204 if _, err := io.ReadFull(zr, b[:1]); err != nil { 205 if err == io.EOF { 206 break // 送信者がストリームを閉じました 207 } 208 log.Fatal(err) 209 } 210 211 // メッセージの内容を読み取る。 212 n := int(b[0]) 213 if _, err := io.ReadFull(zr, b[:n]); err != nil { 214 log.Fatal(err) 215 } 216 217 fmt.Printf("Received %d bytes: %s\n", n, b[:n]) 218 } 219 fmt.Println() 220 221 if err := zr.Close(); err != nil { 222 log.Fatal(err) 223 } 224 }() 225 226 // Output: 227 // Received 1 bytes: A 228 // Received 4 bytes: long 229 // Received 4 bytes: time 230 // Received 3 bytes: ago 231 // Received 2 bytes: in 232 // Received 1 bytes: a 233 // Received 6 bytes: galaxy 234 // Received 4 bytes: far, 235 // Received 3 bytes: far 236 // Received 7 bytes: away... 237 }