github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/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 "bytes" 9 "compress/flate" 10 "fmt" 11 "io" 12 "log" 13 "os" 14 "strings" 15 "sync" 16 ) 17 18 // In performance critical applications, Reset can be used to discard the 19 // current compressor or decompressor state and reinitialize them quickly 20 // by taking advantage of previously allocated memory. 21 func Example_reset() { 22 proverbs := []string{ 23 "Don't communicate by sharing memory, share memory by communicating.\n", 24 "Concurrency is not parallelism.\n", 25 "The bigger the interface, the weaker the abstraction.\n", 26 "Documentation is for users.\n", 27 } 28 29 var r strings.Reader 30 var b bytes.Buffer 31 buf := make([]byte, 32<<10) 32 33 zw, err := flate.NewWriter(nil, flate.DefaultCompression) 34 if err != nil { 35 log.Fatal(err) 36 } 37 zr := flate.NewReader(nil) 38 39 for _, s := range proverbs { 40 r.Reset(s) 41 b.Reset() 42 43 // Reset the compressor and encode from some input stream. 44 zw.Reset(&b) 45 if _, err := io.CopyBuffer(zw, &r, buf); err != nil { 46 log.Fatal(err) 47 } 48 if err := zw.Close(); err != nil { 49 log.Fatal(err) 50 } 51 52 // Reset the decompressor and decode to some output stream. 53 if err := zr.(flate.Resetter).Reset(&b, nil); err != nil { 54 log.Fatal(err) 55 } 56 if _, err := io.CopyBuffer(os.Stdout, zr, buf); err != nil { 57 log.Fatal(err) 58 } 59 if err := zr.Close(); err != nil { 60 log.Fatal(err) 61 } 62 } 63 64 // Output: 65 // Don't communicate by sharing memory, share memory by communicating. 66 // Concurrency is not parallelism. 67 // The bigger the interface, the weaker the abstraction. 68 // Documentation is for users. 69 } 70 71 // A preset dictionary can be used to improve the compression ratio. 72 // The downside to using a dictionary is that the compressor and decompressor 73 // must agree in advance what dictionary to use. 74 func Example_dictionary() { 75 // The dictionary is a string of bytes. When compressing some input data, 76 // the compressor will attempt to substitute substrings with matches found 77 // in the dictionary. As such, the dictionary should only contain substrings 78 // that are expected to be found in the actual data stream. 79 const dict = `<?xml version="1.0"?>` + `<book>` + `<data>` + `<meta name="` + `" content="` 80 81 // The data to compress should (but is not required to) contain frequent 82 // substrings that match those in the dictionary. 83 const data = `<?xml version="1.0"?> 84 <book> 85 <meta name="title" content="The Go Programming Language"/> 86 <meta name="authors" content="Alan Donovan and Brian Kernighan"/> 87 <meta name="published" content="2015-10-26"/> 88 <meta name="isbn" content="978-0134190440"/> 89 <data>...</data> 90 </book> 91 ` 92 93 var b bytes.Buffer 94 95 // Compress the data using the specially crafted dictionary. 96 zw, err := flate.NewWriterDict(&b, flate.DefaultCompression, []byte(dict)) 97 if err != nil { 98 log.Fatal(err) 99 } 100 if _, err := io.Copy(zw, strings.NewReader(data)); err != nil { 101 log.Fatal(err) 102 } 103 if err := zw.Close(); err != nil { 104 log.Fatal(err) 105 } 106 107 // The decompressor must use the same dictionary as the compressor. 108 // Otherwise, the input may appear as corrupted. 109 fmt.Println("Decompressed output using the dictionary:") 110 zr := flate.NewReaderDict(bytes.NewReader(b.Bytes()), []byte(dict)) 111 if _, err := io.Copy(os.Stdout, zr); err != nil { 112 log.Fatal(err) 113 } 114 if err := zr.Close(); err != nil { 115 log.Fatal(err) 116 } 117 118 fmt.Println() 119 120 // Substitute all of the bytes in the dictionary with a '#' to visually 121 // demonstrate the approximate effectiveness of using a preset dictionary. 122 fmt.Println("Substrings matched by the dictionary are marked with #:") 123 hashDict := []byte(dict) 124 for i := range hashDict { 125 hashDict[i] = '#' 126 } 127 zr = flate.NewReaderDict(&b, hashDict) 128 if _, err := io.Copy(os.Stdout, zr); err != nil { 129 log.Fatal(err) 130 } 131 if err := zr.Close(); err != nil { 132 log.Fatal(err) 133 } 134 135 // Output: 136 // Decompressed output using the dictionary: 137 // <?xml version="1.0"?> 138 // <book> 139 // <meta name="title" content="The Go Programming Language"/> 140 // <meta name="authors" content="Alan Donovan and Brian Kernighan"/> 141 // <meta name="published" content="2015-10-26"/> 142 // <meta name="isbn" content="978-0134190440"/> 143 // <data>...</data> 144 // </book> 145 // 146 // Substrings matched by the dictionary are marked with #: 147 // ##################### 148 // ###### 149 // ############title###########The Go Programming Language"/# 150 // ############authors###########Alan Donovan and Brian Kernighan"/# 151 // ############published###########2015-10-26"/# 152 // ############isbn###########978-0134190440"/# 153 // ######...</##### 154 // </##### 155 } 156 157 // DEFLATE is suitable for transmitting compressed data across the network. 158 func Example_synchronization() { 159 var wg sync.WaitGroup 160 defer wg.Wait() 161 162 // Use io.Pipe to simulate a network connection. 163 // A real network application should take care to properly close the 164 // underlying connection. 165 rp, wp := io.Pipe() 166 167 // Start a goroutine to act as the transmitter. 168 wg.Add(1) 169 go func() { 170 defer wg.Done() 171 172 zw, err := flate.NewWriter(wp, flate.BestSpeed) 173 if err != nil { 174 log.Fatal(err) 175 } 176 177 b := make([]byte, 256) 178 for _, m := range strings.Fields("A long time ago in a galaxy far, far away...") { 179 // We use a simple framing format where the first byte is the 180 // message length, followed the message itself. 181 b[0] = uint8(copy(b[1:], m)) 182 183 if _, err := zw.Write(b[:1+len(m)]); err != nil { 184 log.Fatal(err) 185 } 186 187 // Flush ensures that the receiver can read all data sent so far. 188 if err := zw.Flush(); err != nil { 189 log.Fatal(err) 190 } 191 } 192 193 if err := zw.Close(); err != nil { 194 log.Fatal(err) 195 } 196 }() 197 198 // Start a goroutine to act as the receiver. 199 wg.Add(1) 200 go func() { 201 defer wg.Done() 202 203 zr := flate.NewReader(rp) 204 205 b := make([]byte, 256) 206 for { 207 // Read the message length. 208 // This is guaranteed to return for every corresponding 209 // Flush and Close on the transmitter side. 210 if _, err := io.ReadFull(zr, b[:1]); err != nil { 211 if err == io.EOF { 212 break // The transmitter closed the stream 213 } 214 log.Fatal(err) 215 } 216 217 // Read the message content. 218 n := int(b[0]) 219 if _, err := io.ReadFull(zr, b[:n]); err != nil { 220 log.Fatal(err) 221 } 222 223 fmt.Printf("Received %d bytes: %s\n", n, b[:n]) 224 } 225 fmt.Println() 226 227 if err := zr.Close(); err != nil { 228 log.Fatal(err) 229 } 230 }() 231 232 // Output: 233 // Received 1 bytes: A 234 // Received 4 bytes: long 235 // Received 4 bytes: time 236 // Received 3 bytes: ago 237 // Received 2 bytes: in 238 // Received 1 bytes: a 239 // Received 6 bytes: galaxy 240 // Received 4 bytes: far, 241 // Received 3 bytes: far 242 // Received 7 bytes: away... 243 }