content: /*
   * Copyright 2013-2023 the original author or authors.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      https://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.alibaba.cloud.commons.io;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.OutputStream;
  import java.io.Reader;
  import java.io.Writer;
  import java.nio.charset.Charset;
  
  /**
   * The IOUtils. copy from apache commons-io.
   *
   * @author <a href="mailto:chenxilzx1@gmail.com">theonefx</a>
   */
  public final class IOUtils {
  
  	/**
  	 * Represents the end-of-file (or stream).
  	 * @since 2.5 (made public)
  	 */
  	public static final int EOF = -1;
  
  	/**
  	 * The default buffer size ({@value}) to use for.
  	 * {@link #copyLarge(InputStream, java.io.OutputStream)} and
  	 * {@link #copyLarge(Reader, Writer)}
  	 */
  	private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
  
  	private IOUtils() {
  
  	}
  
  	/**
  	 * Gets the contents of an <code>InputStream</code> as a String using the specified
  	 * character encoding.
  	 * <p>
  	 * This method buffers the input internally, so there is no need to use a
  	 * <code>BufferedInputStream</code>.
  	 * </p>
  	 * @param input the <code>InputStream</code> to read from
  	 * @param encoding the encoding to use, null means platform default
  	 * @return the requested String
  	 * @throws NullPointerException if the input is null
  	 * @throws java.io.IOException if an I/O error occurs
  	 * @since 2.3
  	 */
  	public static String toString(final InputStream input, final Charset encoding)
  			throws IOException {
  		try (StringBuilderWriter sw = new StringBuilderWriter()) {
  			copy(input, sw, encoding);
  			return sw.toString();
  		}
  	}
  
  	// copy from Reader
  	// -----------------------------------------------------------------------
  
  	/**
  	 * Copies chars from a <code>Reader</code> to a <code>Writer</code>.
  	 * <p>
  	 * This method buffers the input internally, so there is no need to use a
  	 * <code>BufferedReader</code>.
  	 * <p>
  	 * Large streams (over 2GB) will return a chars copied value of <code>-1</code> after
  	 * the copy has completed since the correct number of chars cannot be returned as an
  	 * int. For large streams use the <code>copyLarge(Reader, Writer)</code> method.
  	 * @param input the <code>Reader</code> to read from
  	 * @param output the <code>Writer</code> to write to
  	 * @return the number of characters copied, or -1 if &gt; Integer.MAX_VALUE
  	 * @throws NullPointerException if the input or output is null
  	 * @throws IOException if an I/O error occurs
  	 * @since 1.1
  	 */
  	public static int copy(final Reader input, final Writer output) throws IOException {
  		final long count = copyLarge(input, output);
  		if (count > Integer.MAX_VALUE) {
  			return -1;
  		}
  		return (int) count;
  	}
  
  	/**
  	 * Copies bytes from an <code>InputStream</code> to chars on a <code>Writer</code>
  	 * using the specified character encoding.
  	 * <p>
  	 * This method buffers the input internally, so there is no need to use a
  	 * <code>BufferedInputStream</code>.
  	 * <p>
  	 * This method uses {@link java.io.InputStreamReader}.
  	 * @param input the <code>InputStream</code> to read from
  	 * @param output the <code>Writer</code> to write to
  	 * @param inputEncoding the encoding to use for the input stream, null means platform
  	 * default
  	 * @throws NullPointerException if the input or output is null
  	 * @throws IOException if an I/O error occurs
  	 * @since 2.3
  	 */
  	public static void copy(final InputStream input, final Writer output,
  			final Charset inputEncoding) throws IOException {
  		final InputStreamReader in = new InputStreamReader(input,
  				Charsets.toCharset(inputEncoding));
  		copy(in, output);
  	}
  
  	/**
  	 * Copies bytes from an <code>InputStream</code> to an <code>OutputStream</code> using
  	 * an internal buffer of the given size.
  	 * <p>
  	 * This method buffers the input internally, so there is no need to use a
  	 * <code>BufferedInputStream</code>.
  	 * <p>
  	 * @param input the <code>InputStream</code> to read from
  	 * @param output the <code>OutputStream</code> to write to
  	 * @param bufferSize the bufferSize used to copy from the input to the output
  	 * @return the number of bytes copied
  	 * @throws NullPointerException if the input or output is null
  	 * @throws IOException if an I/O error occurs
  	 * @since 2.5
  	 */
  	public static long copy(final InputStream input, final OutputStream output,
  			final int bufferSize) throws IOException {
  		return copyLarge(input, output, new byte[bufferSize]);
  	}
  
  	/**
  	 * Copies chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
  	 * <p>
  	 * This method buffers the input internally, so there is no need to use a
  	 * <code>BufferedReader</code>.
  	 * <p>
  	 * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
  	 * @param input the <code>Reader</code> to read from
  	 * @param output the <code>Writer</code> to write to
  	 * @return the number of characters copied
  	 * @throws NullPointerException if the input or output is null
  	 * @throws IOException if an I/O error occurs
  	 * @since 1.3
  	 */
  	public static long copyLarge(final Reader input, final Writer output)
  			throws IOException {
  		return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]);
  	}
  
  	/**
  	 * Copies chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
  	 * <p>
  	 * This method uses the provided buffer, so there is no need to use a
  	 * <code>BufferedReader</code>.
  	 * <p>
  	 * @param input the <code>Reader</code> to read from
  	 * @param output the <code>Writer</code> to write to
  	 * @param buffer the buffer to be used for the copy
  	 * @return the number of characters copied
  	 * @throws NullPointerException if the input or output is null
  	 * @throws IOException if an I/O error occurs
  	 * @since 2.2
  	 */
  	public static long copyLarge(final Reader input, final Writer output,
  			final char[] buffer) throws IOException {
  		long count = 0;
  		int n;
  		while (EOF != (n = input.read(buffer))) {
  			output.write(buffer, 0, n);
  			count += n;
  		}
  		return count;
  	}
  
  	/**
  	 * Copies bytes from a large (over 2GB) <code>InputStream</code> to an
  	 * <code>OutputStream</code>.
  	 * <p>
  	 * This method buffers the input internally, so there is no need to use a
  	 * <code>BufferedInputStream</code>.
  	 * <p>
  	 * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
  	 * @param input the <code>InputStream</code> to read from
  	 * @param output the <code>OutputStream</code> to write to
  	 * @return the number of bytes copied
  	 * @throws NullPointerException if the input or output is null
  	 * @throws IOException if an I/O error occurs
  	 * @since 1.3
  	 */
  	public static long copyLarge(final InputStream input, final OutputStream output)
  			throws IOException {
  		return copy(input, output, DEFAULT_BUFFER_SIZE);
  	}
  
  	/**
  	 * Copies bytes from a large (over 2GB) <code>InputStream</code> to an
  	 * <code>OutputStream</code>.
  	 * <p>
  	 * This method uses the provided buffer, so there is no need to use a
  	 * <code>BufferedInputStream</code>.
  	 * <p>
  	 * @param input the <code>InputStream</code> to read from
  	 * @param output the <code>OutputStream</code> to write to
  	 * @param buffer the buffer to use for the copy
  	 * @return the number of bytes copied
  	 * @throws NullPointerException if the input or output is null
  	 * @throws IOException if an I/O error occurs
  	 * @since 2.2
  	 */
  	public static long copyLarge(final InputStream input, final OutputStream output,
  			final byte[] buffer) throws IOException {
  		long count = 0;
  		int n;
  		while (EOF != (n = input.read(buffer))) {
  			output.write(buffer, 0, n);
  			count += n;
  		}
  		return count;
  	}
  
  }
  