example_test.go 6.5 KB

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