1. /*
  2. * @(#)DeflaterOutputStream.java 1.34 04/01/12
  3. *
  4. * Copyright 2004 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.34, 01/12/04
  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. * Indicates that the stream has been closed.
  33. */
  34. private boolean closed = false;
  35. /**
  36. * Creates a new output stream with the specified compressor and
  37. * buffer size.
  38. * @param out the output stream
  39. * @param def the compressor ("deflater")
  40. * @param size the output buffer size
  41. * @exception IllegalArgumentException if size is <= 0
  42. */
  43. public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
  44. super(out);
  45. if (out == null || def == null) {
  46. throw new NullPointerException();
  47. } else if (size <= 0) {
  48. throw new IllegalArgumentException("buffer size <= 0");
  49. }
  50. this.def = def;
  51. buf = new byte[size];
  52. }
  53. /**
  54. * Creates a new output stream with the specified compressor and
  55. * a default buffer size.
  56. * @param out the output stream
  57. * @param def the compressor ("deflater")
  58. */
  59. public DeflaterOutputStream(OutputStream out, Deflater def) {
  60. this(out, def, 512);
  61. }
  62. boolean usesDefaultDeflater = false;
  63. /**
  64. * Creates a new output stream with a default compressor and buffer size.
  65. * @param out the output stream
  66. */
  67. public DeflaterOutputStream(OutputStream out) {
  68. this(out, new Deflater());
  69. usesDefaultDeflater = true;
  70. }
  71. /**
  72. * Writes a byte to the compressed output stream. This method will
  73. * block until the byte can be written.
  74. * @param b the byte to be written
  75. * @exception IOException if an I/O error has occurred
  76. */
  77. public void write(int b) throws IOException {
  78. byte[] buf = new byte[1];
  79. buf[0] = (byte)(b & 0xff);
  80. write(buf, 0, 1);
  81. }
  82. /**
  83. * Writes an array of bytes to the compressed output stream. This
  84. * method will block until all the bytes are written.
  85. * @param b the data to be written
  86. * @param off the start offset of the data
  87. * @param len the length of the data
  88. * @exception IOException if an I/O error has occurred
  89. */
  90. public void write(byte[] b, int off, int len) throws IOException {
  91. if (def.finished()) {
  92. throw new IOException("write beyond end of stream");
  93. }
  94. if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
  95. throw new IndexOutOfBoundsException();
  96. } else if (len == 0) {
  97. return;
  98. }
  99. if (!def.finished()) {
  100. def.setInput(b, off, len);
  101. while (!def.needsInput()) {
  102. deflate();
  103. }
  104. }
  105. }
  106. /**
  107. * Finishes writing compressed data to the output stream without closing
  108. * the underlying stream. Use this method when applying multiple filters
  109. * in succession to the same output stream.
  110. * @exception IOException if an I/O error has occurred
  111. */
  112. public void finish() throws IOException {
  113. if (!def.finished()) {
  114. def.finish();
  115. while (!def.finished()) {
  116. deflate();
  117. }
  118. }
  119. }
  120. /**
  121. * Writes remaining compressed data to the output stream and closes the
  122. * underlying stream.
  123. * @exception IOException if an I/O error has occurred
  124. */
  125. public void close() throws IOException {
  126. if (!closed) {
  127. finish();
  128. if (usesDefaultDeflater)
  129. def.end();
  130. out.close();
  131. closed = true;
  132. }
  133. }
  134. /**
  135. * Writes next block of compressed data to the output stream.
  136. * @throws IOException if an I/O error has occurred
  137. */
  138. protected void deflate() throws IOException {
  139. int len = def.deflate(buf, 0, buf.length);
  140. if (len > 0) {
  141. out.write(buf, 0, len);
  142. }
  143. }
  144. }