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