1. /*
  2. * @(#)GZIPOutputStream.java 1.17 00/02/02
  3. *
  4. * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.util.zip;
  11. import java.io.OutputStream;
  12. import java.io.IOException;
  13. /**
  14. * This class implements a stream filter for writing compressed data in
  15. * the GZIP file format.
  16. * @version 1.17, 02/02/00
  17. * @author David Connelly
  18. *
  19. */
  20. public
  21. class GZIPOutputStream extends DeflaterOutputStream {
  22. /**
  23. * CRC-32 of uncompressed data.
  24. */
  25. protected CRC32 crc = new CRC32();
  26. /*
  27. * GZIP header magic number.
  28. */
  29. private final static int GZIP_MAGIC = 0x8b1f;
  30. /**
  31. * Creates a new output stream with the specified buffer size.
  32. * @param out the output stream
  33. * @param size the output buffer size
  34. * @exception IOException If an I/O error has occurred.
  35. * @exception IllegalArgumentException if size is <= 0
  36. */
  37. public GZIPOutputStream(OutputStream out, int size) throws IOException {
  38. super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size);
  39. writeHeader();
  40. crc.reset();
  41. }
  42. /**
  43. * Creates a new output stream with a default buffer size.
  44. * @param out the output stream
  45. * @exception IOException If an I/O error has occurred.
  46. */
  47. public GZIPOutputStream(OutputStream out) throws IOException {
  48. this(out, 512);
  49. }
  50. /**
  51. * Writes array of bytes to the compressed output stream. This method
  52. * will block until all the bytes are written.
  53. * @param buf the data to be written
  54. * @param off the start offset of the data
  55. * @param len the length of the data
  56. * @exception IOException If an I/O error has occurred.
  57. */
  58. public synchronized void write(byte[] buf, int off, int len)
  59. throws IOException
  60. {
  61. super.write(buf, off, len);
  62. crc.update(buf, off, len);
  63. }
  64. /**
  65. * Finishes writing compressed data to the output stream without closing
  66. * the underlying stream. Use this method when applying multiple filters
  67. * in succession to the same output stream.
  68. * @exception IOException if an I/O error has occurred
  69. */
  70. public void finish() throws IOException {
  71. if (!def.finished()) {
  72. def.finish();
  73. while (!def.finished()) {
  74. deflate();
  75. }
  76. writeTrailer();
  77. }
  78. }
  79. /**
  80. * Writes remaining compressed data to the output stream and closes the
  81. * underlying stream.
  82. * @exception IOException if an I/O error has occurred
  83. */
  84. public void close() throws IOException {
  85. finish();
  86. out.close();
  87. }
  88. /*
  89. * Writes GZIP member header.
  90. */
  91. private void writeHeader() throws IOException {
  92. writeShort(GZIP_MAGIC); // Magic number
  93. out.write(def.DEFLATED); // Compression method (CM)
  94. out.write(0); // Flags (FLG)
  95. writeInt(0); // Modification time (MTIME)
  96. out.write(0); // Extra flags (XFL)
  97. out.write(0); // Operating system (OS)
  98. }
  99. /*
  100. * Writes GZIP member trailer.
  101. */
  102. private void writeTrailer() throws IOException {
  103. writeInt((int)crc.getValue()); // CRC-32 of uncompressed data
  104. writeInt(def.getTotalIn()); // Number of uncompressed bytes
  105. }
  106. /*
  107. * Writes integer in Intel byte order.
  108. */
  109. private void writeInt(int i) throws IOException {
  110. writeShort(i & 0xffff);
  111. writeShort((i >> 16) & 0xffff);
  112. }
  113. /*
  114. * Writes short integer in Intel byte order.
  115. */
  116. private void writeShort(int s) throws IOException {
  117. out.write(s & 0xff);
  118. out.write((s >> 8) & 0xff);
  119. }
  120. }