1. /*
  2. * @(#)DeflaterOutputStream.java 1.24 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util.zip;
  8. import java.io.FilterOutputStream;
  9. import java.io.OutputStream;
  10. import java.io.InputStream;
  11. import java.io.IOException;
  12. /**
  13. * This class implements an output stream filter for compressing data in
  14. * the "deflate" compression format. It is also used as the basis for other
  15. * types of compression filters, such as GZIPOutputStream.
  16. *
  17. * @see Deflater
  18. * @version 1.24, 11/29/01
  19. * @author David Connelly
  20. */
  21. public
  22. class DeflaterOutputStream extends FilterOutputStream {
  23. /**
  24. * Compressor for this stream.
  25. */
  26. protected Deflater def;
  27. /**
  28. * Output buffer for writing compressed data.
  29. */
  30. protected byte[] buf;
  31. /**
  32. * Creates a new output stream with the specified compressor and
  33. * buffer size.
  34. * @param out the output stream
  35. * @param def the compressor ("deflater")
  36. * @param len the output buffer size
  37. * @exception IllegalArgumentException if size is <= 0
  38. */
  39. public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
  40. super(out);
  41. if (out == null || def == null) {
  42. throw new NullPointerException();
  43. } else if (size <= 0) {
  44. throw new IllegalArgumentException("buffer size <= 0");
  45. }
  46. this.def = def;
  47. buf = new byte[size];
  48. }
  49. /**
  50. * Creates a new output stream with the specified compressor and
  51. * a default buffer size.
  52. * @param out the output stream
  53. * @param def the compressor ("deflater")
  54. */
  55. public DeflaterOutputStream(OutputStream out, Deflater def) {
  56. this(out, def, 512);
  57. }
  58. /**
  59. * Creates a new output stream with a defaul compressor and buffer size.
  60. */
  61. public DeflaterOutputStream(OutputStream out) {
  62. this(out, new Deflater());
  63. }
  64. /**
  65. * Writes a byte to the compressed output stream. This method will
  66. * block until the byte can be written.
  67. * @param b the byte to be written
  68. * @exception IOException if an I/O error has occurred
  69. */
  70. public void write(int b) throws IOException {
  71. byte[] buf = new byte[1];
  72. buf[0] = (byte)(b & 0xff);
  73. write(buf, 0, 1);
  74. }
  75. /**
  76. * Writes an array of bytes to the compressed output stream. This
  77. * method will block until all the bytes are written.
  78. * @param buf the data to be written
  79. * @param off the start offset of the data
  80. * @param len the length of the data
  81. * @exception IOException if an I/O error has occurred
  82. */
  83. public void write(byte[] b, int off, int len) throws IOException {
  84. if (def.finished()) {
  85. throw new IOException("write beyond end of stream");
  86. }
  87. if (!def.finished()) {
  88. def.setInput(b, off, len);
  89. while (!def.needsInput()) {
  90. deflate();
  91. }
  92. }
  93. }
  94. /**
  95. * Finishes writing compressed data to the output stream without closing
  96. * the underlying stream. Use this method when applying multiple filters
  97. * in succession to the same output stream.
  98. * @exception IOException if an I/O error has occurred
  99. */
  100. public void finish() throws IOException {
  101. if (!def.finished()) {
  102. def.finish();
  103. while (!def.finished()) {
  104. deflate();
  105. }
  106. }
  107. }
  108. /**
  109. * Writes remaining compressed data to the output stream and closes the
  110. * underlying stream.
  111. * @exception IOException if an I/O error has occurred
  112. */
  113. public void close() throws IOException {
  114. finish();
  115. out.close();
  116. }
  117. /**
  118. * Writes next block of compressed data to the output stream.
  119. */
  120. protected void deflate() throws IOException {
  121. int len = def.deflate(buf, 0, buf.length);
  122. if (len > 0) {
  123. out.write(buf, 0, len);
  124. }
  125. }
  126. }