code: public static long copy(InputStream inputStream, OutputStream outputStream) throws IOException, IllegalArgumentException
    {
      Params.notNull(inputStream, "Input stream");
      Params.notNull(outputStream, "Output stream");
      Params.isFalse(inputStream instanceof ZipInputStream, "Input stream is ZIP.");
      Params.isFalse(outputStream instanceof ZipOutputStream, "Output stream is ZIP.");
  
      if(!(inputStream instanceof BufferedInputStream)) {
        inputStream = new BufferedInputStream(inputStream);
      }
      if(!(outputStream instanceof BufferedOutputStream)) {
        outputStream = new BufferedOutputStream(outputStream);
      }
  
      long bytes = 0;
      try {
        byte[] buffer = new byte[BUFFER_SIZE];
        int length;
        while((length = inputStream.read(buffer)) != -1) {
          bytes += length;
          outputStream.write(buffer, 0, length);
        }
      }
      finally {
        close(inputStream);
        close(outputStream);
      }
      return bytes;
    }
docs: Copy bytes from input to given output stream then close both byte streams. Please be aware this method closes both
  input and output streams. This is especially important if work with ZIP streams; trying to get/put next ZIP entry
  after this method completes will fail with <em>stream closed</em> exception.
  
  @param inputStream bytes input stream,
  @param outputStream bytes output stream.
  @return the number of bytes processed.
  @throws IOException if reading or writing fails.
  @throws IllegalArgumentException if input or output stream is null or ZIP stream.