deflater.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 524 行 · 第 1/2 页

JAVA
524
字号
   */
  protected void finalize()
  {
    /* Exists solely for compatibility.  We don't have any native state. */
  }

  /** 
   * Flushes the current input block.  Further calls to deflate() will
   * produce enough output to inflate everything in the current input
   * block.  This is not part of Sun's JDK so I have made it package
   * private.  It is used by DeflaterOutputStream to implement
   * flush().
   */
  void flush() {
    state |= IS_FLUSHING;
  }

  /** 
   * Finishes the deflater with the current input block.  It is an error
   * to give more input after this method was called.  This method must
   * be called to force all bytes to be flushed.
   */
  public void finish() {
    state |= IS_FLUSHING | IS_FINISHING;
  }

  /** 
   * Returns true iff the stream was finished and no more output bytes
   * are available.
   */
  public boolean finished()
  {
    return state == FINISHED_STATE && pending.isFlushed();
  }

  /**
   * Returns true, if the input buffer is empty.
   * You should then call setInput(). <br>
   *
   * <em>NOTE</em>: This method can also return true when the stream
   * was finished.  
   */
  public boolean needsInput()
  {
    return engine.needsInput();
  }

  /**
   * Sets the data which should be compressed next.  This should be only
   * called when needsInput indicates that more input is needed.
   * If you call setInput when needsInput() returns false, the
   * previous input that is still pending will be thrown away.
   * The given byte array should not be changed, before needsInput() returns
   * true again.
   * This call is equivalent to <code>setInput(input, 0, input.length)</code>.
   * @param input the buffer containing the input data.
   * @exception IllegalStateException if the buffer was finished() or ended().
   */
  public void setInput(byte[] input)
  {
    setInput(input, 0, input.length);
  }

  /**
   * Sets the data which should be compressed next.  This should be
   * only called when needsInput indicates that more input is needed.
   * The given byte array should not be changed, before needsInput() returns
   * true again.
   * @param input the buffer containing the input data.
   * @param off the start of the data.
   * @param len the length of the data.  
   * @exception IllegalStateException if the buffer was finished() or ended()
   * or if previous input is still pending.
   */
  public void setInput(byte[] input, int off, int len)
  {
    if ((state & IS_FINISHING) != 0)
      throw new IllegalStateException("finish()/end() already called");
    engine.setInput(input, off, len);
  }

  /** 
   * Sets the compression level.  There is no guarantee of the exact
   * position of the change, but if you call this when needsInput is
   * true the change of compression level will occur somewhere near
   * before the end of the so far given input.  
   * @param lvl the new compression level.
   */
  public void setLevel(int lvl)
  {
    if (lvl == DEFAULT_COMPRESSION)
      lvl = 6;
    else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION)
      throw new IllegalArgumentException();


    if (level != lvl)
      {
	level = lvl;
	engine.setLevel(lvl);
      }
  }

  /** 
   * Sets the compression strategy. Strategy is one of
   * DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED.  For the exact
   * position where the strategy is changed, the same as for
   * setLevel() applies.
   * @param stgy the new compression strategy.
   */
  public void setStrategy(int stgy)
  {
    if (stgy != DEFAULT_STRATEGY && stgy != FILTERED
	&& stgy != HUFFMAN_ONLY)
      throw new IllegalArgumentException();
    engine.setStrategy(stgy);
  }

  /**
   * Deflates the current input block to the given array.  It returns 
   * the number of bytes compressed, or 0 if either 
   * needsInput() or finished() returns true or length is zero.
   * @param output the buffer where to write the compressed data.
   */
  public int deflate(byte[] output)
  {
    return deflate(output, 0, output.length);
  }

  /**
   * Deflates the current input block to the given array.  It returns 
   * the number of bytes compressed, or 0 if either 
   * needsInput() or finished() returns true or length is zero.
   * @param output the buffer where to write the compressed data.
   * @param offset the offset into the output array.
   * @param length the maximum number of bytes that may be written.
   * @exception IllegalStateException if end() was called.
   * @exception IndexOutOfBoundsException if offset and/or length
   * don't match the array length.  
   */
  public int deflate(byte[] output, int offset, int length)
  {
    int origLength = length;

    if (state == CLOSED_STATE)
      throw new IllegalStateException("Deflater closed");

    if (state < BUSY_STATE)
      {
	/* output header */
	int header = (DEFLATED + 
		      ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8;
	int level_flags = (level - 1) >> 1;
	if (level_flags < 0 || level_flags > 3) 
	  level_flags = 3;
	header |= level_flags << 6;
	if ((state & IS_SETDICT) != 0)
	  /* Dictionary was set */
	  header |= DeflaterConstants.PRESET_DICT;
	header += 31 - (header % 31);

	pending.writeShortMSB(header);
	if ((state & IS_SETDICT) != 0)
	  {
	    int chksum = engine.getAdler();
	    engine.resetAdler();
	    pending.writeShortMSB(chksum >> 16);
	    pending.writeShortMSB(chksum & 0xffff);
	  }

	state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING));
      }

    for (;;)
      {
	int count = pending.flush(output, offset, length);
	offset += count;
	totalOut += count;
	length -= count;
	if (length == 0 || state == FINISHED_STATE)
	  break;

	if (!engine.deflate((state & IS_FLUSHING) != 0, 
			    (state & IS_FINISHING) != 0))
	  {
	    if (state == BUSY_STATE)
	      /* We need more input now */
	      return origLength - length;
	    else if (state == FLUSHING_STATE)
	      {
		if (level != NO_COMPRESSION)
		  {
		    /* We have to supply some lookahead.  8 bit lookahead
		     * are needed by the zlib inflater, and we must fill 
		     * the next byte, so that all bits are flushed.
		     */
		    int neededbits = 8 + ((-pending.getBitCount()) & 7);
		    while (neededbits > 0)
		      {
			/* write a static tree block consisting solely of
			 * an EOF:
			 */
			pending.writeBits(2, 10);
			neededbits -= 10;
		      }
		  }
		state = BUSY_STATE;
	      }
	    else if (state == FINISHING_STATE)
	      {
		pending.alignToByte();
		/* We have completed the stream */
		if (!noHeader)
		  {
		    int adler = engine.getAdler();
		    pending.writeShortMSB(adler >> 16);
		    pending.writeShortMSB(adler & 0xffff);
		  }
		state = FINISHED_STATE;
	      }
	  }
      }

    return origLength - length;
  }

  /**
   * Sets the dictionary which should be used in the deflate process.
   * This call is equivalent to <code>setDictionary(dict, 0,
   * dict.length)</code>.  
   * @param dict the dictionary.  
   * @exception IllegalStateException if setInput () or deflate ()
   * were already called or another dictionary was already set.  
   */
  public void setDictionary(byte[] dict)
  {
    setDictionary(dict, 0, dict.length);
  }

  /**
   * Sets the dictionary which should be used in the deflate process.
   * The dictionary should be a byte array containing strings that are
   * likely to occur in the data which should be compressed.  The
   * dictionary is not stored in the compressed output, only a
   * checksum.  To decompress the output you need to supply the same
   * dictionary again.
   * @param dict the dictionary.
   * @param offset an offset into the dictionary.
   * @param length the length of the dictionary.
   * @exception IllegalStateException if setInput () or deflate () were
   * already called or another dictionary was already set.
   */
  public void setDictionary(byte[] dict, int offset, int length)
  {
    if (state != INIT_STATE)
      throw new IllegalStateException();

    state = SETDICT_STATE;
    engine.setDictionary(dict, offset, length);
  }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?