code: public void encode(OutputStream out, byte[] data, int off, int len) throws IOException {
      if (out == null) {
        throw new NullPointerException("out");
      } else if (data == null) {
        throw new NullPointerException("data");
      } else if (off < 0 || len < 0 || (off + len) < 0 || off > data.length || (off + len) > data.length) {
        throw new IndexOutOfBoundsException();
      } else if (len == 0) {
        return;
      }
  
      long current = 0;
      int n = 0;
  
      for (int i = 0; i < len; i++) {
        int b = data[off + i] & 0xFF;
        int code = codes[b];
        int nbits = lengths[b];
  
        current <<= nbits;
        current |= code;
        n += nbits;
  
        while (n >= 8) {
          n -= 8;
          out.write(((int)(current >> n)));
        }
      }
  
      if (n > 0) {
        current <<= (8 - n);
        current |= (0xFF >>> n); // this should be EOS symbol
        out.write((int)current);
      }
    }
docs: Compresses the input string literal using the Huffman coding.
  @param  out  the output stream for the compressed data
  @param  data the string literal to be Huffman encoded
  @param  off  the start offset in the data
  @param  len  the number of bytes to encode
  @throws IOException if an I/O error occurs. In particular,
  an <code>IOException</code> may be thrown if the
  output stream has been closed.