001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.io;
019
020import java.io.BufferedInputStream;
021import java.io.BufferedOutputStream;
022import java.io.BufferedReader;
023import java.io.BufferedWriter;
024import java.io.ByteArrayInputStream;
025import java.io.CharArrayWriter;
026import java.io.Closeable;
027import java.io.EOFException;
028import java.io.File;
029import java.io.IOException;
030import java.io.InputStream;
031import java.io.InputStreamReader;
032import java.io.OutputStream;
033import java.io.OutputStreamWriter;
034import java.io.PipedInputStream;
035import java.io.PipedOutputStream;
036import java.io.Reader;
037import java.io.UncheckedIOException;
038import java.io.Writer;
039import java.net.HttpURLConnection;
040import java.net.ServerSocket;
041import java.net.Socket;
042import java.net.URI;
043import java.net.URL;
044import java.net.URLConnection;
045import java.nio.ByteBuffer;
046import java.nio.CharBuffer;
047import java.nio.channels.Channels;
048import java.nio.channels.ReadableByteChannel;
049import java.nio.channels.Selector;
050import java.nio.charset.Charset;
051import java.nio.charset.StandardCharsets;
052import java.nio.file.Files;
053import java.util.Arrays;
054import java.util.Collection;
055import java.util.Iterator;
056import java.util.List;
057import java.util.Objects;
058import java.util.function.Consumer;
059import java.util.function.Supplier;
060import java.util.stream.Collectors;
061import java.util.stream.Stream;
062import java.util.zip.InflaterInputStream;
063
064import org.apache.commons.io.channels.FileChannels;
065import org.apache.commons.io.function.IOConsumer;
066import org.apache.commons.io.function.IOSupplier;
067import org.apache.commons.io.function.IOTriFunction;
068import org.apache.commons.io.input.BoundedInputStream;
069import org.apache.commons.io.input.CharSequenceReader;
070import org.apache.commons.io.input.QueueInputStream;
071import org.apache.commons.io.output.AppendableWriter;
072import org.apache.commons.io.output.ByteArrayOutputStream;
073import org.apache.commons.io.output.NullOutputStream;
074import org.apache.commons.io.output.NullWriter;
075import org.apache.commons.io.output.StringBuilderWriter;
076import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
077
078/**
079 * General IO stream manipulation utilities.
080 * <p>
081 * This class provides static utility methods for input/output operations.
082 * </p>
083 * <ul>
084 * <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
085 * <li>toXxx/read - these methods read data from a stream
086 * <li>write - these methods write data to a stream
087 * <li>copy - these methods copy all the data from one stream to another
088 * <li>contentEquals - these methods compare the content of two streams
089 * </ul>
090 * <p>
091 * The byte-to-char methods and char-to-byte methods involve a conversion step.
092 * Two methods are provided in each case, one that uses the platform default
093 * encoding and the other which allows you to specify an encoding. You are
094 * encouraged to always specify an encoding because relying on the platform
095 * default can lead to unexpected results, for example when moving from
096 * development to production.
097 * </p>
098 * <p>
099 * All the methods in this class that read a stream are buffered internally.
100 * This means that there is no cause to use a {@link BufferedInputStream}
101 * or {@link BufferedReader}. The default buffer size of 4K has been shown
102 * to be efficient in tests.
103 * </p>
104 * <p>
105 * The various copy methods all delegate the actual copying to one of the following methods:
106 * </p>
107 * <ul>
108 * <li>{@link #copyLarge(InputStream, OutputStream, byte[])}</li>
109 * <li>{@link #copyLarge(InputStream, OutputStream, long, long, byte[])}</li>
110 * <li>{@link #copyLarge(Reader, Writer, char[])}</li>
111 * <li>{@link #copyLarge(Reader, Writer, long, long, char[])}</li>
112 * </ul>
113 * For example, {@link #copy(InputStream, OutputStream)} calls {@link #copyLarge(InputStream, OutputStream)}
114 * which calls {@link #copy(InputStream, OutputStream, int)} which creates the buffer and calls
115 * {@link #copyLarge(InputStream, OutputStream, byte[])}.
116 * <p>
117 * Applications can re-use buffers by using the underlying methods directly.
118 * This may improve performance for applications that need to do a lot of copying.
119 * </p>
120 * <p>
121 * Wherever possible, the methods in this class do <em>not</em> flush or close
122 * the stream. This is to avoid making non-portable assumptions about the
123 * streams' origin and further use. Thus the caller is still responsible for
124 * closing streams after use.
125 * </p>
126 * <p>
127 * Provenance: Excalibur.
128 * </p>
129 */
130public class IOUtils {
131    // NOTE: This class is focused on InputStream, OutputStream, Reader and
132    // Writer. Each method should take at least one of these as a parameter,
133    // or return one of them.
134
135    /**
136     * Holder for per-thread internal scratch buffer.
137     *
138     * <p>Buffers are created lazily and reused within the same thread to reduce allocation overhead. In the rare case of reentrant access, a temporary buffer
139     * is allocated to avoid data corruption.</p>
140     *
141     * <p>Typical usage:</p>
142     *
143     * <pre>{@code
144     * try (ScratchBytes scratch = ScratchBytes.get()) {
145     *     // use the buffer
146     *     byte[] bytes = scratch.array();
147     *     // ...
148     * }
149     * }</pre>
150     */
151    static final class ScratchBytes implements AutoCloseable {
152
153        /**
154         * Wraps an internal byte array.
155         *
156         * [0] boolean in use.
157         * [1] byte[] buffer.
158         */
159        private static final ThreadLocal<Object[]> LOCAL = ThreadLocal.withInitial(() -> new Object[] { false, byteArray() });
160
161        private static final ScratchBytes INSTANCE = new ScratchBytes(null);
162
163        /**
164         * Gets the internal byte array buffer.
165         *
166         * @return the internal byte array buffer.
167         */
168        static ScratchBytes get() {
169            final Object[] holder = LOCAL.get();
170            // If already in use, return a new array
171            if ((boolean) holder[0]) {
172                return new ScratchBytes(byteArray());
173            }
174            holder[0] = true;
175            return INSTANCE;
176        }
177
178        /**
179         * The buffer, or null if using the thread-local buffer.
180         */
181        private final byte[] buffer;
182
183        private ScratchBytes(final byte[] buffer) {
184            this.buffer = buffer;
185        }
186
187        byte[] array() {
188            return buffer != null ? buffer : (byte[]) LOCAL.get()[1];
189        }
190
191        /**
192         * If the buffer is the internal array, clear and release it for reuse.
193         */
194        @Override
195        public void close() {
196            if (buffer == null) {
197                final Object[] holder = LOCAL.get();
198                Arrays.fill((byte[]) holder[1], (byte) 0);
199                holder[0] = false;
200            }
201        }
202    }
203
204    /**
205     * Holder for per-thread internal scratch buffer.
206     *
207     * <p>Buffers are created lazily and reused within the same thread to reduce allocation overhead. In the rare case of reentrant access, a temporary buffer
208     * is allocated to avoid data corruption.</p>
209     *
210     * <p>Typical usage:</p>
211     *
212     * <pre>{@code
213     * try (ScratchChars scratch = ScratchChars.get()) {
214     *     // use the buffer
215     *     char[] bytes = scratch.array();
216     *     // ...
217     * }
218     * }</pre>
219     */
220    static final class ScratchChars implements AutoCloseable {
221
222        /**
223         * Wraps an internal char array.
224         *
225         * [0] boolean in use.
226         * [1] char[] buffer.
227         */
228        private static final ThreadLocal<Object[]> LOCAL = ThreadLocal.withInitial(() -> new Object[] { false, charArray() });
229
230        private static final ScratchChars INSTANCE = new ScratchChars(null);
231
232        /**
233         * Gets the internal char array buffer.
234         *
235         * @return the internal char array buffer.
236         */
237        static ScratchChars get() {
238            final Object[] holder = LOCAL.get();
239            // If already in use, return a new array
240            if ((boolean) holder[0]) {
241                return new ScratchChars(charArray());
242            }
243            holder[0] = true;
244            return INSTANCE;
245        }
246
247        /**
248         * The buffer, or null if using the thread-local buffer.
249         */
250        private final char[] buffer;
251
252        private ScratchChars(final char[] buffer) {
253            this.buffer = buffer;
254        }
255
256        char[] array() {
257            return buffer != null ? buffer : (char[]) LOCAL.get()[1];
258        }
259
260        /**
261         * If the buffer is the internal array, clear and release it for reuse.
262         */
263        @Override
264        public void close() {
265            if (buffer == null) {
266                final Object[] holder = LOCAL.get();
267                Arrays.fill((char[]) holder[1], (char) 0);
268                holder[0] = false;
269            }
270        }
271    }
272
273    /**
274     * CR char '{@value}'.
275     *
276     * @since 2.9.0
277     */
278    public static final int CR = '\r';
279
280    /**
281     * The default buffer size ({@value}) to use in copy methods.
282     */
283    public static final int DEFAULT_BUFFER_SIZE = 8192;
284
285    /**
286     * The system directory separator character.
287     */
288    public static final char DIR_SEPARATOR = File.separatorChar;
289
290    /**
291     * The Unix directory separator character '{@value}'.
292     */
293    public static final char DIR_SEPARATOR_UNIX = '/';
294
295    /**
296     * The Windows directory separator character '{@value}'.
297     */
298    public static final char DIR_SEPARATOR_WINDOWS = '\\';
299
300    /**
301     * A singleton empty byte array.
302     *
303     *  @since 2.9.0
304     */
305    public static final byte[] EMPTY_BYTE_ARRAY = {};
306
307    /**
308     * Represents the end-of-file (or stream) value {@value}.
309     * @since 2.5 (made public)
310     */
311    public static final int EOF = -1;
312
313    /**
314     * LF char '{@value}'.
315     *
316     * @since 2.9.0
317     */
318    public static final int LF = '\n';
319
320    /**
321     * The system line separator string.
322     *
323     * @deprecated Use {@link System#lineSeparator()}.
324     */
325    @Deprecated
326    public static final String LINE_SEPARATOR = System.lineSeparator();
327
328    /**
329     * The Unix line separator string.
330     *
331     * @see StandardLineSeparator#LF
332     */
333    public static final String LINE_SEPARATOR_UNIX = StandardLineSeparator.LF.getString();
334
335    /**
336     * The Windows line separator string.
337     *
338     * @see StandardLineSeparator#CRLF
339     */
340    public static final String LINE_SEPARATOR_WINDOWS = StandardLineSeparator.CRLF.getString();
341
342    /**
343     * The maximum size of an array in many Java VMs.
344     * <p>
345     * The constant is copied from OpenJDK's {@code jdk.internal.util.ArraysSupport#SOFT_MAX_ARRAY_LENGTH}.
346     * </p>
347     *
348     * @since 2.21.0
349     */
350    public static final int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
351
352    /**
353     * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a
354     * BufferedInputStream from the given InputStream.
355     *
356     * @param inputStream the InputStream to wrap or return (not null).
357     * @return the given InputStream or a new {@link BufferedInputStream} for the given InputStream.
358     * @throws NullPointerException if the input parameter is null.
359     * @since 2.5
360     */
361    @SuppressWarnings("resource") // parameter null check
362    public static BufferedInputStream buffer(final InputStream inputStream) {
363        // reject null early on rather than waiting for IO operation to fail
364        // not checked by BufferedInputStream
365        Objects.requireNonNull(inputStream, "inputStream");
366        return inputStream instanceof BufferedInputStream ?
367                (BufferedInputStream) inputStream : new BufferedInputStream(inputStream);
368    }
369
370    /**
371     * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a
372     * BufferedInputStream from the given InputStream.
373     *
374     * @param inputStream the InputStream to wrap or return (not null).
375     * @param size the buffer size, if a new BufferedInputStream is created.
376     * @return the given InputStream or a new {@link BufferedInputStream} for the given InputStream.
377     * @throws NullPointerException if the input parameter is null.
378     * @since 2.5
379     */
380    @SuppressWarnings("resource") // parameter null check
381    public static BufferedInputStream buffer(final InputStream inputStream, final int size) {
382        // reject null early on rather than waiting for IO operation to fail
383        // not checked by BufferedInputStream
384        Objects.requireNonNull(inputStream, "inputStream");
385        return inputStream instanceof BufferedInputStream ?
386                (BufferedInputStream) inputStream : new BufferedInputStream(inputStream, size);
387    }
388
389    /**
390     * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a
391     * BufferedOutputStream from the given OutputStream.
392     *
393     * @param outputStream the OutputStream to wrap or return (not null).
394     * @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream
395     * @throws NullPointerException if the input parameter is null.
396     * @since 2.5
397     */
398    @SuppressWarnings("resource") // parameter null check
399    public static BufferedOutputStream buffer(final OutputStream outputStream) {
400        // reject null early on rather than waiting for IO operation to fail
401        // not checked by BufferedInputStream
402        Objects.requireNonNull(outputStream, "outputStream");
403        return outputStream instanceof BufferedOutputStream ?
404                (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream);
405    }
406
407    /**
408     * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a
409     * BufferedOutputStream from the given OutputStream.
410     *
411     * @param outputStream the OutputStream to wrap or return (not null).
412     * @param size the buffer size, if a new BufferedOutputStream is created.
413     * @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream.
414     * @throws NullPointerException if the input parameter is null.
415     * @since 2.5
416     */
417    @SuppressWarnings("resource") // parameter null check
418    public static BufferedOutputStream buffer(final OutputStream outputStream, final int size) {
419        // reject null early on rather than waiting for IO operation to fail
420        // not checked by BufferedInputStream
421        Objects.requireNonNull(outputStream, "outputStream");
422        return outputStream instanceof BufferedOutputStream ?
423                (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream, size);
424    }
425
426    /**
427     * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from
428     * the given reader.
429     *
430     * @param reader the reader to wrap or return (not null).
431     * @return the given reader or a new {@link BufferedReader} for the given reader.
432     * @throws NullPointerException if the input parameter is null.
433     * @since 2.5
434     */
435    public static BufferedReader buffer(final Reader reader) {
436        return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader);
437    }
438
439    /**
440     * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from the
441     * given reader.
442     *
443     * @param reader the reader to wrap or return (not null).
444     * @param size the buffer size, if a new BufferedReader is created.
445     * @return the given reader or a new {@link BufferedReader} for the given reader.
446     * @throws NullPointerException if the input parameter is null.
447     * @since 2.5
448     */
449    public static BufferedReader buffer(final Reader reader, final int size) {
450        return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader, size);
451    }
452
453    /**
454     * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the
455     * given Writer.
456     *
457     * @param writer the Writer to wrap or return (not null).
458     * @return the given Writer or a new {@link BufferedWriter} for the given Writer.
459     * @throws NullPointerException if the input parameter is null.
460     * @since 2.5
461     */
462    public static BufferedWriter buffer(final Writer writer) {
463        return writer instanceof BufferedWriter ? (BufferedWriter) writer : new BufferedWriter(writer);
464    }
465
466    /**
467     * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the
468     * given Writer.
469     *
470     * @param writer the Writer to wrap or return (not null).
471     * @param size the buffer size, if a new BufferedWriter is created.
472     * @return the given Writer or a new {@link BufferedWriter} for the given Writer.
473     * @throws NullPointerException if the input parameter is null.
474     * @since 2.5
475     */
476    public static BufferedWriter buffer(final Writer writer, final int size) {
477        return writer instanceof BufferedWriter ? (BufferedWriter) writer : new BufferedWriter(writer, size);
478    }
479
480    /**
481     * Returns a new byte array of size {@link #DEFAULT_BUFFER_SIZE}.
482     *
483     * @return a new byte array of size {@link #DEFAULT_BUFFER_SIZE}.
484     * @since 2.9.0
485     */
486    public static byte[] byteArray() {
487        return byteArray(DEFAULT_BUFFER_SIZE);
488    }
489
490    /**
491     * Returns a new byte array of the given size.
492     *
493     * TODO Consider guarding or warning against large allocations.
494     *
495     * @param size array size.
496     * @return a new byte array of the given size.
497     * @throws NegativeArraySizeException if the size is negative.
498     * @since 2.9.0
499     */
500    public static byte[] byteArray(final int size) {
501        return new byte[size];
502    }
503
504    /**
505     * Returns a new char array of size {@link #DEFAULT_BUFFER_SIZE}.
506     *
507     * @return a new char array of size {@link #DEFAULT_BUFFER_SIZE}.
508     * @since 2.9.0
509     */
510    private static char[] charArray() {
511        return charArray(DEFAULT_BUFFER_SIZE);
512    }
513
514    /**
515     * Returns a new char array of the given size.
516     *
517     * TODO Consider guarding or warning against large allocations.
518     *
519     * @param size array size.
520     * @return a new char array of the given size.
521     * @since 2.9.0
522     */
523    private static char[] charArray(final int size) {
524        return new char[size];
525    }
526
527    /**
528     * Validates that the sub-range {@code [off, off + len)} is within the bounds of the given array.
529     *
530     * <p>The range is valid if all of the following hold:</p>
531     * <ul>
532     *   <li>{@code off >= 0}</li>
533     *   <li>{@code len >= 0}</li>
534     *   <li>{@code off + len <= array.length}</li>
535     * </ul>
536     *
537     * <p>If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.</p>
538     *
539     * <p>Typical usage in {@link InputStream#read(byte[], int, int)} and {@link OutputStream#write(byte[], int, int)} implementations:</p>
540     *
541     * <pre><code>
542     * public int read(byte[] b, int off, int len) throws IOException {
543     *     IOUtils.checkFromIndexSize(b, off, len);
544     *     if (len == 0) {
545     *         return 0;
546     *     }
547     *     ensureOpen();
548     *     // perform read...
549     * }
550     *
551     * public void write(byte[] b, int off, int len) throws IOException {
552     *     IOUtils.checkFromIndexSize(b, off, len);
553     *     if (len == 0) {
554     *         return;
555     *     }
556     *     ensureOpen();
557     *     // perform write...
558     * }
559     * </code></pre>
560     *
561     * @param array the array against which the range is validated
562     * @param off   the starting offset into the array (inclusive)
563     * @param len   the number of elements to access
564     * @throws NullPointerException      if {@code array} is {@code null}
565     * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}
566     * @see InputStream#read(byte[], int, int)
567     * @see OutputStream#write(byte[], int, int)
568     * @since 2.21.0
569     */
570    public static void checkFromIndexSize(final byte[] array, final int off, final int len) {
571        checkFromIndexSize(off, len, Objects.requireNonNull(array, "byte array").length);
572    }
573
574    /**
575     * Validates that the sub-range {@code [off, off + len)} is within the bounds of the given array.
576     *
577     * <p>The range is valid if all of the following hold:</p>
578     * <ul>
579     *   <li>{@code off >= 0}</li>
580     *   <li>{@code len >= 0}</li>
581     *   <li>{@code off + len <= array.length}</li>
582     * </ul>
583     *
584     * <p>If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.</p>
585     *
586     * <p>Typical usage in {@link Reader#read(char[], int, int)} and {@link Writer#write(char[], int, int)} implementations:</p>
587     *
588     * <pre><code>
589     * public int read(char[] cbuf, int off, int len) throws IOException {
590     *     ensureOpen();
591     *     IOUtils.checkFromIndexSize(cbuf, off, len);
592     *     if (len == 0) {
593     *         return 0;
594     *     }
595     *     // perform read...
596     * }
597     *
598     * public void write(char[] cbuf, int off, int len) throws IOException {
599     *     ensureOpen();
600     *     IOUtils.checkFromIndexSize(cbuf, off, len);
601     *     if (len == 0) {
602     *         return;
603     *     }
604     *     // perform write...
605     * }
606     * </code></pre>
607     *
608     * @param array the array against which the range is validated
609     * @param off   the starting offset into the array (inclusive)
610     * @param len   the number of characters to access
611     * @throws NullPointerException      if {@code array} is {@code null}
612     * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}
613     * @see Reader#read(char[], int, int)
614     * @see Writer#write(char[], int, int)
615     * @since 2.21.0
616     */
617    public static void checkFromIndexSize(final char[] array, final int off, final int len) {
618        checkFromIndexSize(off, len, Objects.requireNonNull(array, "char array").length);
619    }
620
621    static void checkFromIndexSize(final int off, final int len, final int arrayLength) {
622        if ((off | len | arrayLength) < 0 || arrayLength - len < off) {
623            throw new IndexOutOfBoundsException(String.format("Range [%s, %<s + %s) out of bounds for length %s", off, len, arrayLength));
624        }
625    }
626
627    /**
628     * Validates that the sub-range {@code [off, off + len)} is within the bounds of the given string.
629     *
630     * <p>The range is valid if all of the following hold:</p>
631     * <ul>
632     *   <li>{@code off >= 0}</li>
633     *   <li>{@code len >= 0}</li>
634     *   <li>{@code off + len <= str.length()}</li>
635     * </ul>
636     *
637     * <p>If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.</p>
638     *
639     * <p>Typical usage in {@link Writer#write(String, int, int)} implementations:</p>
640     *
641     * <pre><code>
642     * public void write(String str, int off, int len) throws IOException {
643     *     IOUtils.checkFromIndexSize(str, off, len);
644     *     if (len == 0) {
645     *         return;
646     *     }
647     *     // perform write...
648     * }
649     * </code></pre>
650     *
651     * @param str the string against which the range is validated
652     * @param off the starting offset into the string (inclusive)
653     * @param len the number of characters to write
654     * @throws NullPointerException      if {@code str} is {@code null}
655     * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code str}
656     * @see Writer#write(String, int, int)
657     * @since 2.21.0
658     */
659    public static void checkFromIndexSize(final String str, final int off, final int len) {
660        checkFromIndexSize(off, len, Objects.requireNonNull(str, "str").length());
661    }
662
663    /**
664     * Validates that the sub-sequence {@code [fromIndex, toIndex)} is within the bounds of the given {@link CharSequence}.
665     *
666     * <p>The sub-sequence is valid if all of the following hold:</p>
667     * <ul>
668     *   <li>{@code fromIndex >= 0}</li>
669     *   <li>{@code fromIndex <= toIndex}</li>
670     *   <li>{@code toIndex <= seq.length()}</li>
671     * </ul>
672     *
673     * <p>If {@code seq} is {@code null}, it is treated as the literal string {@code "null"} (length {@code 4}).</p>
674     *
675     * <p>If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.</p>
676     *
677     * <p>Typical usage in {@link Appendable#append(CharSequence, int, int)} implementations:</p>
678     *
679     * <pre><code>
680     * public Appendable append(CharSequence csq, int start, int end) throws IOException {
681     *     IOUtils.checkFromToIndex(csq, start, end);
682     *     // perform append...
683     *     return this;
684     * }
685     * </code></pre>
686     *
687     * @param seq       the character sequence to validate (may be {@code null}, treated as {@code "null"})
688     * @param fromIndex the starting index (inclusive)
689     * @param toIndex   the ending index (exclusive)
690     * @throws IndexOutOfBoundsException if the range {@code [fromIndex, toIndex)} is out of bounds for {@code seq}
691     * @see Appendable#append(CharSequence, int, int)
692     * @since 2.21.0
693     */
694    public static void checkFromToIndex(final CharSequence seq, final int fromIndex, final int toIndex) {
695        checkFromToIndex(fromIndex, toIndex, seq != null ? seq.length() : 4);
696    }
697
698    static void checkFromToIndex(final int fromIndex, final int toIndex, final int length) {
699        if (fromIndex < 0 || toIndex < fromIndex || length < toIndex) {
700            throw new IndexOutOfBoundsException(String.format("Range [%s, %s) out of bounds for length %s", fromIndex, toIndex, length));
701        }
702    }
703
704    /**
705     * Clears any state.
706     * <ul>
707     * <li>Removes the current thread's value for thread-local variables.</li>
708     * <li>Sets static scratch arrays to 0s.</li>
709     * </ul>
710     * @see IO#clear()
711     */
712    static void clear() {
713        ScratchBytes.LOCAL.remove();
714        ScratchChars.LOCAL.remove();
715    }
716
717    /**
718     * Closes the given {@link Closeable} as a null-safe operation.
719     *
720     * @param closeable The resource to close, may be null.
721     * @throws IOException if an I/O error occurs.
722     * @since 2.7
723     */
724    public static void close(final Closeable closeable) throws IOException {
725        if (closeable != null) {
726            closeable.close();
727        }
728    }
729
730    /**
731     * Closes the given {@link Closeable}s as null-safe operations.
732     *
733     * @param closeables The resource(s) to close, may be null.
734     * @throws IOExceptionList if an I/O error occurs.
735     * @since 2.8.0
736     */
737    public static void close(final Closeable... closeables) throws IOExceptionList {
738        IOConsumer.forAll(IOUtils::close, closeables);
739    }
740
741    /**
742     * Closes the given {@link Closeable} as a null-safe operation.
743     *
744     * @param closeable The resource to close, may be null.
745     * @param consumer Consume the IOException thrown by {@link Closeable#close()}.
746     * @throws IOException if an I/O error occurs.
747     * @since 2.7
748     */
749    public static void close(final Closeable closeable, final IOConsumer<IOException> consumer) throws IOException {
750        if (closeable != null) {
751            try {
752                closeable.close();
753            } catch (final IOException e) {
754                if (consumer != null) {
755                    consumer.accept(e);
756                }
757            } catch (final Exception e) {
758                if (consumer != null) {
759                    consumer.accept(new IOException(e));
760                }
761            }
762        }
763    }
764
765    /**
766     * Closes a URLConnection.
767     *
768     * @param conn the connection to close.
769     * @since 2.4
770     */
771    public static void close(final URLConnection conn) {
772        if (conn instanceof HttpURLConnection) {
773            ((HttpURLConnection) conn).disconnect();
774        }
775    }
776
777    /**
778     * Avoids the need to type cast.
779     *
780     * @param closeable the object to close, may be null.
781     */
782    private static void closeQ(final Closeable closeable) {
783        closeQuietly(closeable, null);
784    }
785
786    /**
787     * Closes a {@link Closeable} unconditionally.
788     *
789     * <p>
790     * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in
791     * finally blocks.
792     * <p>
793     * Example code:
794     * </p>
795     * <pre>
796     * Closeable closeable = null;
797     * try {
798     *     closeable = new FileReader(&quot;foo.txt&quot;);
799     *     // process closeable
800     *     closeable.close();
801     * } catch (Exception e) {
802     *     // error handling
803     * } finally {
804     *     IOUtils.closeQuietly(closeable);
805     * }
806     * </pre>
807     * <p>
808     * Closing all streams:
809     * </p>
810     * <pre>
811     * try {
812     *     return IOUtils.copy(inputStream, outputStream);
813     * } finally {
814     *     IOUtils.closeQuietly(inputStream);
815     *     IOUtils.closeQuietly(outputStream);
816     * }
817     * </pre>
818     * <p>
819     * Also consider using a try-with-resources statement where appropriate.
820     * </p>
821     *
822     * @param closeable the objects to close, may be null or already closed.
823     * @since 2.0
824     * @see Throwable#addSuppressed(Throwable)
825     */
826    public static void closeQuietly(final Closeable closeable) {
827        closeQuietly(closeable, null);
828    }
829
830    /**
831     * Closes a {@link Closeable} unconditionally.
832     * <p>
833     * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored.
834     * <p>
835     * This is typically used in finally blocks to ensure that the closeable is closed
836     * even if an Exception was thrown before the normal close statement was reached.
837     * <br>
838     * <b>It should not be used to replace the close statement(s)
839     * which should be present for the non-exceptional case.</b>
840     * <br>
841     * It is only intended to simplify tidying up where normal processing has already failed
842     * and reporting close failure as well is not necessary or useful.
843     * <p>
844     * Example code:
845     * </p>
846     * <pre>
847     * Closeable closeable = null;
848     * try {
849     *     closeable = new FileReader(&quot;foo.txt&quot;);
850     *     // processing using the closeable; may throw an Exception
851     *     closeable.close(); // Normal close - exceptions not ignored
852     * } catch (Exception e) {
853     *     // error handling
854     * } finally {
855     *     <strong>IOUtils.closeQuietly(closeable); // In case normal close was skipped due to Exception</strong>
856     * }
857     * </pre>
858     * <p>
859     * Closing all streams:
860     * <br>
861     * <pre>
862     * try {
863     *     return IOUtils.copy(inputStream, outputStream);
864     * } finally {
865     *     IOUtils.closeQuietly(inputStream, outputStream);
866     * }
867     * </pre>
868     * <p>
869     * Also consider using a try-with-resources statement where appropriate.
870     * </p>
871     * @param closeables the objects to close, may be null or already closed.
872     * @see #closeQuietly(Closeable)
873     * @since 2.5
874     * @see Throwable#addSuppressed(Throwable)
875     */
876    public static void closeQuietly(final Closeable... closeables) {
877        if (closeables != null) {
878            closeQuietly(Arrays.stream(closeables));
879        }
880    }
881
882    /**
883     * Closes the given {@link Closeable} as a null-safe operation while consuming IOException by the given {@code consumer}.
884     *
885     * @param closeable The resource to close, may be null.
886     * @param consumer Consumes the Exception thrown by {@link Closeable#close()}.
887     * @since 2.7
888     */
889    public static void closeQuietly(final Closeable closeable, final Consumer<Exception> consumer) {
890        if (closeable != null) {
891            try {
892                closeable.close();
893            } catch (final Exception e) {
894                if (consumer != null) {
895                    consumer.accept(e);
896                }
897            }
898        }
899    }
900
901    /**
902     * Closes an {@link InputStream} unconditionally.
903     * <p>
904     * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
905     * This is typically used in finally blocks.
906     * </p>
907     * <p>
908     * Example code:
909     * </p>
910     * <pre>
911     *   byte[] data = new byte[1024];
912     *   InputStream in = null;
913     *   try {
914     *       in = new FileInputStream("foo.txt");
915     *       in.read(data);
916     *       in.close(); //close errors are handled
917     *   } catch (Exception e) {
918     *       // error handling
919     *   } finally {
920     *       IOUtils.closeQuietly(in);
921     *   }
922     * </pre>
923     * <p>
924     * Also consider using a try-with-resources statement where appropriate.
925     * </p>
926     *
927     * @param input the InputStream to close, may be null or already closed.
928     * @see Throwable#addSuppressed(Throwable)
929     */
930    public static void closeQuietly(final InputStream input) {
931        closeQ(input);
932    }
933
934    /**
935     * Closes an iterable of {@link Closeable} unconditionally.
936     * <p>
937     * Equivalent calling {@link Closeable#close()} on each element, except any exceptions will be ignored.
938     * </p>
939     *
940     * @param closeables the objects to close, may be null or already closed.
941     * @see #closeQuietly(Closeable)
942     * @since 2.12.0
943     */
944    public static void closeQuietly(final Iterable<Closeable> closeables) {
945        if (closeables != null) {
946            closeables.forEach(IOUtils::closeQuietly);
947        }
948    }
949
950    /**
951     * Closes an {@link OutputStream} unconditionally.
952     * <p>
953     * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
954     * This is typically used in finally blocks.
955     * </p>
956     * <p>
957     * Example code:
958     * </p>
959     * <pre>
960     * byte[] data = "Hello, World".getBytes();
961     *
962     * OutputStream out = null;
963     * try {
964     *     out = new FileOutputStream("foo.txt");
965     *     out.write(data);
966     *     out.close(); //close errors are handled
967     * } catch (IOException e) {
968     *     // error handling
969     * } finally {
970     *     IOUtils.closeQuietly(out);
971     * }
972     * </pre>
973     * <p>
974     * Also consider using a try-with-resources statement where appropriate.
975     * </p>
976     *
977     * @param output the OutputStream to close, may be null or already closed.
978     * @see Throwable#addSuppressed(Throwable)
979     */
980    public static void closeQuietly(final OutputStream output) {
981        closeQ(output);
982    }
983
984    /**
985     * Closes an {@link Reader} unconditionally.
986     * <p>
987     * Equivalent to {@link Reader#close()}, except any exceptions will be ignored.
988     * This is typically used in finally blocks.
989     * </p>
990     * <p>
991     * Example code:
992     * </p>
993     * <pre>
994     *   char[] data = new char[1024];
995     *   Reader in = null;
996     *   try {
997     *       in = new FileReader("foo.txt");
998     *       in.read(data);
999     *       in.close(); //close errors are handled
1000     *   } catch (Exception e) {
1001     *       // error handling
1002     *   } finally {
1003     *       IOUtils.closeQuietly(in);
1004     *   }
1005     * </pre>
1006     * <p>
1007     * Also consider using a try-with-resources statement where appropriate.
1008     * </p>
1009     *
1010     * @param reader the Reader to close, may be null or already closed.
1011     * @see Throwable#addSuppressed(Throwable)
1012     */
1013    public static void closeQuietly(final Reader reader) {
1014        closeQ(reader);
1015    }
1016
1017    /**
1018     * Closes a {@link Selector} unconditionally.
1019     * <p>
1020     * Equivalent to {@link Selector#close()}, except any exceptions will be ignored.
1021     * This is typically used in finally blocks.
1022     * </p>
1023     * <p>
1024     * Example code:
1025     * </p>
1026     * <pre>
1027     *   Selector selector = null;
1028     *   try {
1029     *       selector = Selector.open();
1030     *       // process socket
1031     *
1032     *   } catch (Exception e) {
1033     *       // error handling
1034     *   } finally {
1035     *       IOUtils.closeQuietly(selector);
1036     *   }
1037     * </pre>
1038     * <p>
1039     * Also consider using a try-with-resources statement where appropriate.
1040     * </p>
1041     *
1042     * @param selector the Selector to close, may be null or already closed.
1043     * @since 2.2
1044     * @see Throwable#addSuppressed(Throwable)
1045     */
1046    public static void closeQuietly(final Selector selector) {
1047        closeQ(selector);
1048    }
1049
1050    /**
1051     * Closes a {@link ServerSocket} unconditionally.
1052     * <p>
1053     * Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored.
1054     * This is typically used in finally blocks.
1055     * </p>
1056     * <p>
1057     * Example code:
1058     * </p>
1059     * <pre>
1060     *   ServerSocket socket = null;
1061     *   try {
1062     *       socket = new ServerSocket();
1063     *       // process socket
1064     *       socket.close();
1065     *   } catch (Exception e) {
1066     *       // error handling
1067     *   } finally {
1068     *       IOUtils.closeQuietly(socket);
1069     *   }
1070     * </pre>
1071     * <p>
1072     * Also consider using a try-with-resources statement where appropriate.
1073     * </p>
1074     *
1075     * @param serverSocket the ServerSocket to close, may be null or already closed.
1076     * @since 2.2
1077     * @see Throwable#addSuppressed(Throwable)
1078     */
1079    public static void closeQuietly(final ServerSocket serverSocket) {
1080        closeQ(serverSocket);
1081    }
1082
1083    /**
1084     * Closes a {@link Socket} unconditionally.
1085     * <p>
1086     * Equivalent to {@link Socket#close()}, except any exceptions will be ignored.
1087     * This is typically used in finally blocks.
1088     * </p>
1089     * <p>
1090     * Example code:
1091     * </p>
1092     * <pre>
1093     *   Socket socket = null;
1094     *   try {
1095     *       socket = new Socket("http://www.foo.com/", 80);
1096     *       // process socket
1097     *       socket.close();
1098     *   } catch (Exception e) {
1099     *       // error handling
1100     *   } finally {
1101     *       IOUtils.closeQuietly(socket);
1102     *   }
1103     * </pre>
1104     * <p>
1105     * Also consider using a try-with-resources statement where appropriate.
1106     * </p>
1107     *
1108     * @param socket the Socket to close, may be null or already closed.
1109     * @since 2.0
1110     * @see Throwable#addSuppressed(Throwable)
1111     */
1112    public static void closeQuietly(final Socket socket) {
1113        closeQ(socket);
1114    }
1115
1116    /**
1117     * Closes a stream of {@link Closeable} unconditionally.
1118     * <p>
1119     * Equivalent calling {@link Closeable#close()} on each element, except any exceptions will be ignored.
1120     * </p>
1121     *
1122     * @param closeables the objects to close, may be null or already closed.
1123     * @see #closeQuietly(Closeable)
1124     * @since 2.12.0
1125     */
1126    public static void closeQuietly(final Stream<Closeable> closeables) {
1127        if (closeables != null) {
1128            closeables.forEach(IOUtils::closeQuietly);
1129        }
1130    }
1131
1132    /**
1133     * Closes an {@link Writer} unconditionally.
1134     * <p>
1135     * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
1136     * This is typically used in finally blocks.
1137     * </p>
1138     * <p>
1139     * Example code:
1140     * </p>
1141     * <pre>
1142     *   Writer out = null;
1143     *   try {
1144     *       out = new StringWriter();
1145     *       out.write("Hello World");
1146     *       out.close(); //close errors are handled
1147     *   } catch (Exception e) {
1148     *       // error handling
1149     *   } finally {
1150     *       IOUtils.closeQuietly(out);
1151     *   }
1152     * </pre>
1153     * <p>
1154     * Also consider using a try-with-resources statement where appropriate.
1155     * </p>
1156     *
1157     * @param writer the Writer to close, may be null or already closed.
1158     * @see Throwable#addSuppressed(Throwable)
1159     */
1160    public static void closeQuietly(final Writer writer) {
1161        closeQ(writer);
1162    }
1163
1164    /**
1165     * Consumes bytes from a {@link InputStream} and ignores them.
1166     * <p>
1167     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1168     * </p>
1169     *
1170     * @param input the {@link InputStream} to read.
1171     * @return the number of bytes copied. or {@code 0} if {@code input is null}.
1172     * @throws NullPointerException if the InputStream is {@code null}.
1173     * @throws IOException if an I/O error occurs.
1174     * @since 2.8.0
1175     */
1176    public static long consume(final InputStream input) throws IOException {
1177        return copyLarge(input, NullOutputStream.INSTANCE);
1178    }
1179
1180    /**
1181     * Consumes characters from a {@link Reader} and ignores them.
1182     * <p>
1183     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1184     * </p>
1185     *
1186     * @param input the {@link Reader} to read.
1187     * @return the number of bytes copied. or {@code 0} if {@code input is null}.
1188     * @throws NullPointerException if the Reader is {@code null}.
1189     * @throws IOException if an I/O error occurs.
1190     * @since 2.12.0
1191     */
1192    public static long consume(final Reader input) throws IOException {
1193        return copyLarge(input, NullWriter.INSTANCE);
1194    }
1195
1196    /**
1197     * Compares the contents of two Streams to determine if they are equal or
1198     * not.
1199     * <p>
1200     * This method buffers the input internally using
1201     * {@link BufferedInputStream} if they are not already buffered.
1202     * </p>
1203     *
1204     * @param input1 the first stream.
1205     * @param input2 the second stream.
1206     * @return true if the content of the streams are equal or they both don't.
1207     * exist, false otherwise.
1208     * @throws IOException          if an I/O error occurs.
1209     */
1210    @SuppressWarnings("resource") // Caller closes input streams
1211    public static boolean contentEquals(final InputStream input1, final InputStream input2) throws IOException {
1212        // Before making any changes, please test with org.apache.commons.io.jmh.IOUtilsContentEqualsInputStreamsBenchmark
1213        if (input1 == input2) {
1214            return true;
1215        }
1216        if (input1 == null || input2 == null) {
1217            return false;
1218        }
1219        // We do not close FileChannels because that closes the owning InputStream.
1220        return FileChannels.contentEquals(Channels.newChannel(input1), Channels.newChannel(input2), DEFAULT_BUFFER_SIZE);
1221    }
1222
1223    // TODO Consider making public
1224    private static boolean contentEquals(final Iterator<?> iterator1, final Iterator<?> iterator2) {
1225        while (iterator1.hasNext()) {
1226            if (!iterator2.hasNext()) {
1227                return false;
1228            }
1229            if (!Objects.equals(iterator1.next(), iterator2.next())) {
1230                return false;
1231            }
1232        }
1233        return !iterator2.hasNext();
1234    }
1235
1236    /**
1237     * Compares the contents of two Readers to determine if they are equal or not.
1238     * <p>
1239     * This method buffers the input internally using {@link BufferedReader} if they are not already buffered.
1240     * </p>
1241     *
1242     * @param input1 the first reader.
1243     * @param input2 the second reader.
1244     * @return true if the content of the readers are equal or they both don't exist, false otherwise.
1245     * @throws NullPointerException if either input is null.
1246     * @throws IOException if an I/O error occurs.
1247     * @since 1.1
1248     */
1249    public static boolean contentEquals(final Reader input1, final Reader input2) throws IOException {
1250        if (input1 == input2) {
1251            return true;
1252        }
1253        if (input1 == null || input2 == null) {
1254            return false;
1255        }
1256
1257        // reuse one
1258        try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
1259            final char[] array1 = scratch.array();
1260            // but allocate another
1261            final char[] array2 = charArray();
1262            int pos1;
1263            int pos2;
1264            int count1;
1265            int count2;
1266            while (true) {
1267                pos1 = 0;
1268                pos2 = 0;
1269                for (int index = 0; index < DEFAULT_BUFFER_SIZE; index++) {
1270                    if (pos1 == index) {
1271                        do {
1272                            count1 = input1.read(array1, pos1, DEFAULT_BUFFER_SIZE - pos1);
1273                        } while (count1 == 0);
1274                        if (count1 == EOF) {
1275                            return pos2 == index && input2.read() == EOF;
1276                        }
1277                        pos1 += count1;
1278                    }
1279                    if (pos2 == index) {
1280                        do {
1281                            count2 = input2.read(array2, pos2, DEFAULT_BUFFER_SIZE - pos2);
1282                        } while (count2 == 0);
1283                        if (count2 == EOF) {
1284                            return pos1 == index && input1.read() == EOF;
1285                        }
1286                        pos2 += count2;
1287                    }
1288                    if (array1[index] != array2[index]) {
1289                        return false;
1290                    }
1291                }
1292            }
1293        }
1294    }
1295
1296    // TODO Consider making public
1297    private static boolean contentEquals(final Stream<?> stream1, final Stream<?> stream2) {
1298        if (stream1 == stream2) {
1299            return true;
1300        }
1301        if (stream1 == null || stream2 == null) {
1302            return false;
1303        }
1304        return contentEquals(stream1.iterator(), stream2.iterator());
1305    }
1306
1307    // TODO Consider making public
1308    private static boolean contentEqualsIgnoreEOL(final BufferedReader reader1, final BufferedReader reader2) {
1309        if (reader1 == reader2) {
1310            return true;
1311        }
1312        if (reader1 == null || reader2 == null) {
1313            return false;
1314        }
1315        return contentEquals(reader1.lines(), reader2.lines());
1316    }
1317
1318    /**
1319     * Compares the contents of two Readers to determine if they are equal or
1320     * not, ignoring EOL characters.
1321     * <p>
1322     * This method buffers the input internally using
1323     * {@link BufferedReader} if they are not already buffered.
1324     * </p>
1325     *
1326     * @param reader1 the first reader.
1327     * @param reader2 the second reader.
1328     * @return true if the content of the readers are equal (ignoring EOL differences),  false otherwise.
1329     * @throws NullPointerException if either input is null.
1330     * @throws UncheckedIOException if an I/O error occurs.
1331     * @since 2.2
1332     */
1333    @SuppressWarnings("resource")
1334    public static boolean contentEqualsIgnoreEOL(final Reader reader1, final Reader reader2) throws UncheckedIOException {
1335        if (reader1 == reader2) {
1336            return true;
1337        }
1338        if (reader1 == null || reader2 == null) {
1339            return false;
1340        }
1341        return contentEqualsIgnoreEOL(toBufferedReader(reader1), toBufferedReader(reader2));
1342    }
1343
1344    /**
1345     * Copies bytes from an {@link InputStream} to an {@link OutputStream}.
1346     * <p>
1347     * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
1348     * </p>
1349     * <p>
1350     * Large streams (over 2GB) will return a bytes copied value of {@code -1} after the copy has completed since
1351     * the correct number of bytes cannot be returned as an int. For large streams use the
1352     * {@link #copyLarge(InputStream, OutputStream)} method.
1353     * </p>
1354     *
1355     * @param inputStream the {@link InputStream} to read.
1356     * @param outputStream the {@link OutputStream} to write.
1357     * @return the number of bytes copied, or -1 if greater than {@link Integer#MAX_VALUE}.
1358     * @throws NullPointerException if the InputStream is {@code null}.
1359     * @throws NullPointerException if the OutputStream is {@code null}.
1360     * @throws IOException if an I/O error occurs.
1361     * @since 1.1
1362     */
1363    public static int copy(final InputStream inputStream, final OutputStream outputStream) throws IOException {
1364        final long count = copyLarge(inputStream, outputStream);
1365        return count > Integer.MAX_VALUE ? EOF : (int) count;
1366    }
1367
1368    /**
1369     * Copies bytes from an {@link InputStream} to an {@link OutputStream} using an internal buffer of the
1370     * given size.
1371     * <p>
1372     * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
1373     * </p>
1374     *
1375     * @param inputStream the {@link InputStream} to read.
1376     * @param outputStream the {@link OutputStream} to write to.
1377     * @param bufferSize the bufferSize used to copy from the input to the output.
1378     * @return the number of bytes copied.
1379     * @throws NullPointerException if the InputStream is {@code null}.
1380     * @throws NullPointerException if the OutputStream is {@code null}.
1381     * @throws IOException if an I/O error occurs.
1382     * @since 2.5
1383     */
1384    public static long copy(final InputStream inputStream, final OutputStream outputStream, final int bufferSize) throws IOException {
1385        return copyLarge(inputStream, outputStream, byteArray(bufferSize));
1386    }
1387
1388    /**
1389     * Copies bytes from an {@link InputStream} to chars on a
1390     * {@link Writer} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
1391     * <p>
1392     * This method buffers the input internally, so there is no need to use a
1393     * {@link BufferedInputStream}.
1394     * </p>
1395     * <p>
1396     * This method uses {@link InputStreamReader}.
1397     * </p>
1398     *
1399     * @param input the {@link InputStream} to read.
1400     * @param writer the {@link Writer} to write to.
1401     * @throws NullPointerException if the input or output is null.
1402     * @throws IOException          if an I/O error occurs.
1403     * @since 1.1
1404     * @deprecated Use {@link #copy(InputStream, Writer, Charset)} instead.
1405     */
1406    @Deprecated
1407    public static void copy(final InputStream input, final Writer writer) throws IOException {
1408        copy(input, writer, Charset.defaultCharset());
1409    }
1410
1411    /**
1412     * Copies bytes from an {@link InputStream} to chars on a
1413     * {@link Writer} using the specified character encoding.
1414     * <p>
1415     * This method buffers the input internally, so there is no need to use a
1416     * {@link BufferedInputStream}.
1417     * </p>
1418     * <p>
1419     * This method uses {@link InputStreamReader}.
1420     * </p>
1421     *
1422     * @param input the {@link InputStream} to read.
1423     * @param writer the {@link Writer} to write to.
1424     * @param inputCharset the charset to use for the input stream, null means platform default.
1425     * @throws NullPointerException if the input or output is null.
1426     * @throws IOException          if an I/O error occurs.
1427     * @since 2.3
1428     */
1429    public static void copy(final InputStream input, final Writer writer, final Charset inputCharset) throws IOException {
1430        copy(new InputStreamReader(input, Charsets.toCharset(inputCharset)), writer);
1431    }
1432
1433    /**
1434     * Copies bytes from an {@link InputStream} to chars on a
1435     * {@link Writer} using the specified character encoding.
1436     * <p>
1437     * This method buffers the input internally, so there is no need to use a
1438     * {@link BufferedInputStream}.
1439     * </p>
1440     * <p>
1441     * Character encoding names can be found at
1442     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
1443     * </p>
1444     * <p>
1445     * This method uses {@link InputStreamReader}.
1446     * </p>
1447     *
1448     * @param input the {@link InputStream} to read
1449     * @param writer the {@link Writer} to write to
1450     * @param inputCharsetName the name of the requested charset for the InputStream, null means platform default.
1451     * @throws NullPointerException                         if the input or output is null.
1452     * @throws IOException                                  if an I/O error occurs.
1453     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
1454     * @since 1.1
1455     */
1456    public static void copy(final InputStream input, final Writer writer, final String inputCharsetName) throws IOException {
1457        copy(input, writer, Charsets.toCharset(inputCharsetName));
1458    }
1459
1460    /**
1461     * Copies bytes from a {@link ByteArrayOutputStream} to a {@link QueueInputStream}.
1462     * <p>
1463     * Unlike using JDK {@link PipedInputStream} and {@link PipedOutputStream} for this, this
1464     * solution works safely in a single thread environment.
1465     * </p>
1466     * <p>
1467     * Example usage:
1468     * </p>
1469     *
1470     * <pre>
1471     * ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
1472     * outputStream.writeBytes("hello world".getBytes(StandardCharsets.UTF_8));
1473     *
1474     * InputStream inputStream = IOUtils.copy(outputStream);
1475     * </pre>
1476     *
1477     * @param outputStream the {@link ByteArrayOutputStream} to read.
1478     * @return the {@link QueueInputStream} filled with the content of the outputStream.
1479     * @throws NullPointerException if the {@link ByteArrayOutputStream} is {@code null}.
1480     * @throws IOException if an I/O error occurs.
1481     * @since 2.12
1482     */
1483    @SuppressWarnings("resource") // streams are closed by the caller.
1484    public static QueueInputStream copy(final java.io.ByteArrayOutputStream outputStream) throws IOException {
1485        Objects.requireNonNull(outputStream, "outputStream");
1486        final QueueInputStream in = new QueueInputStream();
1487        outputStream.writeTo(in.newQueueOutputStream());
1488        return in;
1489    }
1490
1491    /**
1492     * Copies chars from a {@link Reader} to a {@link Appendable}.
1493     * <p>
1494     * This method buffers the input internally, so there is no need to use a
1495     * {@link BufferedReader}.
1496     * </p>
1497     * <p>
1498     * Large streams (over 2GB) will return a chars copied value of
1499     * {@code -1} after the copy has completed since the correct
1500     * number of chars cannot be returned as an int. For large streams
1501     * use the {@link #copyLarge(Reader, Writer)} method.
1502     * </p>
1503     *
1504     * @param reader the {@link Reader} to read.
1505     * @param output the {@link Appendable} to write to.
1506     * @return the number of characters copied, or -1 if &gt; Integer.MAX_VALUE.
1507     * @throws NullPointerException if the input or output is null.
1508     * @throws IOException          if an I/O error occurs.
1509     * @since 2.7
1510     */
1511    public static long copy(final Reader reader, final Appendable output) throws IOException {
1512        return copy(reader, output, CharBuffer.allocate(DEFAULT_BUFFER_SIZE));
1513    }
1514
1515    /**
1516     * Copies chars from a {@link Reader} to an {@link Appendable}.
1517     * <p>
1518     * This method uses the provided buffer, so there is no need to use a
1519     * {@link BufferedReader}.
1520     * </p>
1521     *
1522     * @param reader the {@link Reader} to read.
1523     * @param output the {@link Appendable} to write to.
1524     * @param buffer the buffer to be used for the copy.
1525     * @return the number of characters copied.
1526     * @throws NullPointerException if the input or output is null.
1527     * @throws IOException          if an I/O error occurs.
1528     * @since 2.7
1529     */
1530    public static long copy(final Reader reader, final Appendable output, final CharBuffer buffer) throws IOException {
1531        long count = 0;
1532        int n;
1533        while (EOF != (n = reader.read(buffer))) {
1534            buffer.flip();
1535            output.append(buffer, 0, n);
1536            count += n;
1537        }
1538        return count;
1539    }
1540
1541    /**
1542     * Copies chars from a {@link Reader} to bytes on an {@link OutputStream} using the the virtual machine's {@linkplain Charset#defaultCharset() default
1543     * charset}, and calling flush.
1544     * <p>
1545     * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
1546     * </p>
1547     * <p>
1548     * Due to the implementation of OutputStreamWriter, this method performs a flush.
1549     * </p>
1550     * <p>
1551     * This method uses {@link OutputStreamWriter}.
1552     * </p>
1553     *
1554     * @param reader the {@link Reader} to read.
1555     * @param output the {@link OutputStream} to write to.
1556     * @throws NullPointerException if the input or output is null.
1557     * @throws IOException          if an I/O error occurs.
1558     * @since 1.1
1559     * @deprecated Use {@link #copy(Reader, OutputStream, Charset)} instead
1560     */
1561    @Deprecated
1562    public static void copy(final Reader reader, final OutputStream output) throws IOException {
1563        copy(reader, output, Charset.defaultCharset());
1564    }
1565
1566    /**
1567     * Copies chars from a {@link Reader} to bytes on an {@link OutputStream} using the specified character encoding, and calling flush.
1568     * <p>
1569     * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
1570     * </p>
1571     * <p>
1572     * Due to the implementation of OutputStreamWriter, this method performs a flush.
1573     * </p>
1574     * <p>
1575     * This method uses {@link OutputStreamWriter}.
1576     * </p>
1577     *
1578     * @param reader        the {@link Reader} to read.
1579     * @param output        the {@link OutputStream} to write to.
1580     * @param outputCharset the charset to use for the OutputStream, null means platform default.
1581     * @throws NullPointerException if the input or output is null.
1582     * @throws IOException          if an I/O error occurs.
1583     * @since 2.3
1584     */
1585    public static void copy(final Reader reader, final OutputStream output, final Charset outputCharset) throws IOException {
1586        final OutputStreamWriter writer = new OutputStreamWriter(output, Charsets.toCharset(outputCharset));
1587        copy(reader, writer);
1588        // XXX Unless anyone is planning on rewriting OutputStreamWriter,
1589        // we have to flush here.
1590        writer.flush();
1591    }
1592
1593    /**
1594     * Copies chars from a {@link Reader} to bytes on an {@link OutputStream} using the specified character encoding, and calling flush.
1595     * <p>
1596     * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
1597     * </p>
1598     * <p>
1599     * Character encoding names can be found at <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
1600     * </p>
1601     * <p>
1602     * Due to the implementation of OutputStreamWriter, this method performs a flush.
1603     * </p>
1604     * <p>
1605     * This method uses {@link OutputStreamWriter}.
1606     * </p>
1607     *
1608     * @param reader            the {@link Reader} to read.
1609     * @param output            the {@link OutputStream} to write to.
1610     * @param outputCharsetName the name of the requested charset for the OutputStream, null means platform default.
1611     * @throws NullPointerException                         if the input or output is null.
1612     * @throws IOException                                  if an I/O error occurs.
1613     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
1614     * @since 1.1
1615     */
1616    public static void copy(final Reader reader, final OutputStream output, final String outputCharsetName) throws IOException {
1617        copy(reader, output, Charsets.toCharset(outputCharsetName));
1618    }
1619
1620    /**
1621     * Copies chars from a {@link Reader} to a {@link Writer}.
1622     * <p>
1623     * This method buffers the input internally, so there is no need to use a
1624     * {@link BufferedReader}.
1625     * </p>
1626     * <p>
1627     * Large streams (over 2GB) will return a chars copied value of
1628     * {@code -1} after the copy has completed since the correct
1629     * number of chars cannot be returned as an int. For large streams
1630     * use the {@link #copyLarge(Reader, Writer)} method.
1631     * </p>
1632     *
1633     * @param reader the {@link Reader} to read.
1634     * @param writer the {@link Writer} to write.
1635     * @return the number of characters copied, or -1 if &gt; Integer.MAX_VALUE.
1636     * @throws NullPointerException if the input or output is null.
1637     * @throws IOException          if an I/O error occurs.
1638     * @since 1.1
1639     */
1640    public static int copy(final Reader reader, final Writer writer) throws IOException {
1641        final long count = copyLarge(reader, writer);
1642        if (count > Integer.MAX_VALUE) {
1643            return EOF;
1644        }
1645        return (int) count;
1646    }
1647
1648    /**
1649     * Copies bytes from a {@link URL} to an {@link OutputStream}.
1650     * <p>
1651     * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
1652     * </p>
1653     * <p>
1654     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1655     * </p>
1656     *
1657     * @param url the {@link URL} to read.
1658     * @param file the {@link OutputStream} to write.
1659     * @return the number of bytes copied.
1660     * @throws NullPointerException if the URL is {@code null}.
1661     * @throws NullPointerException if the OutputStream is {@code null}.
1662     * @throws IOException if an I/O error occurs.
1663     * @since 2.9.0
1664     */
1665    public static long copy(final URL url, final File file) throws IOException {
1666        try (OutputStream outputStream = Files.newOutputStream(Objects.requireNonNull(file, "file").toPath())) {
1667            return copy(url, outputStream);
1668        }
1669    }
1670
1671    /**
1672     * Copies bytes from a {@link URL} to an {@link OutputStream}.
1673     * <p>
1674     * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
1675     * </p>
1676     * <p>
1677     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1678     * </p>
1679     *
1680     * @param url the {@link URL} to read.
1681     * @param outputStream the {@link OutputStream} to write.
1682     * @return the number of bytes copied.
1683     * @throws NullPointerException if the URL is {@code null}.
1684     * @throws NullPointerException if the OutputStream is {@code null}.
1685     * @throws IOException if an I/O error occurs.
1686     * @since 2.9.0
1687     */
1688    public static long copy(final URL url, final OutputStream outputStream) throws IOException {
1689        try (InputStream inputStream = Objects.requireNonNull(url, "url").openStream()) {
1690            return copyLarge(inputStream, outputStream);
1691        }
1692    }
1693
1694    /**
1695     * Copies bytes from a large (over 2GB) {@link InputStream} to an
1696     * {@link OutputStream}.
1697     * <p>
1698     * This method buffers the input internally, so there is no need to use a
1699     * {@link BufferedInputStream}.
1700     * </p>
1701     * <p>
1702     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1703     * </p>
1704     *
1705     * @param inputStream the {@link InputStream} to read.
1706     * @param outputStream the {@link OutputStream} to write.
1707     * @return the number of bytes copied.
1708     * @throws NullPointerException if the InputStream is {@code null}.
1709     * @throws NullPointerException if the OutputStream is {@code null}.
1710     * @throws IOException if an I/O error occurs.
1711     * @since 1.3
1712     */
1713    public static long copyLarge(final InputStream inputStream, final OutputStream outputStream)
1714            throws IOException {
1715        return copy(inputStream, outputStream, DEFAULT_BUFFER_SIZE);
1716    }
1717
1718    /**
1719     * Copies bytes from a large (over 2GB) {@link InputStream} to an
1720     * {@link OutputStream}.
1721     * <p>
1722     * This method uses the provided buffer, so there is no need to use a
1723     * {@link BufferedInputStream}.
1724     * </p>
1725     *
1726     * @param inputStream the {@link InputStream} to read.
1727     * @param outputStream the {@link OutputStream} to write.
1728     * @param buffer the buffer to use for the copy
1729     * @return the number of bytes copied.
1730     * @throws NullPointerException if the InputStream is {@code null}.
1731     * @throws NullPointerException if the OutputStream is {@code null}.
1732     * @throws IOException if an I/O error occurs.
1733     * @since 2.2
1734     */
1735    @SuppressWarnings("resource") // streams are closed by the caller.
1736    public static long copyLarge(final InputStream inputStream, final OutputStream outputStream, final byte[] buffer)
1737        throws IOException {
1738        Objects.requireNonNull(inputStream, "inputStream");
1739        Objects.requireNonNull(outputStream, "outputStream");
1740        long count = 0;
1741        int n;
1742        while (EOF != (n = inputStream.read(buffer))) {
1743            outputStream.write(buffer, 0, n);
1744            count += n;
1745        }
1746        return count;
1747    }
1748
1749    /**
1750     * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an
1751     * {@link OutputStream}, optionally skipping input bytes.
1752     * <p>
1753     * This method buffers the input internally, so there is no need to use a
1754     * {@link BufferedInputStream}.
1755     * </p>
1756     * <p>
1757     * Note that the implementation uses {@link #skip(InputStream, long)}.
1758     * This means that the method may be considerably less efficient than using the actual skip implementation,
1759     * this is done to guarantee that the correct number of characters are skipped.
1760     * </p>
1761     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1762     *
1763     * @param input the {@link InputStream} to read.
1764     * @param output the {@link OutputStream} to write.
1765     * @param inputOffset number of bytes to skip from input before copying, these bytes are ignored.
1766     * @param length number of bytes to copy.
1767     * @return the number of bytes copied.
1768     * @throws NullPointerException if the input or output is null.
1769     * @throws IOException          if an I/O error occurs.
1770     * @since 2.2
1771     */
1772    public static long copyLarge(final InputStream input, final OutputStream output, final long inputOffset, final long length) throws IOException {
1773        try (ScratchBytes scratch = ScratchBytes.get()) {
1774            return copyLarge(input, output, inputOffset, length, scratch.array());
1775        }
1776    }
1777
1778    /**
1779     * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an
1780     * {@link OutputStream}, optionally skipping input bytes.
1781     * <p>
1782     * This method uses the provided buffer, so there is no need to use a
1783     * {@link BufferedInputStream}.
1784     * </p>
1785     * <p>
1786     * Note that the implementation uses {@link #skip(InputStream, long)}.
1787     * This means that the method may be considerably less efficient than using the actual skip implementation,
1788     * this is done to guarantee that the correct number of characters are skipped.
1789     * </p>
1790     *
1791     * @param input the {@link InputStream} to read.
1792     * @param output the {@link OutputStream} to write.
1793     * @param inputOffset number of bytes to skip from input before copying, these bytes are ignored.
1794     * @param length number of bytes to copy.
1795     * @param buffer the buffer to use for the copy.
1796     * @return the number of bytes copied.
1797     * @throws NullPointerException if the input or output is null.
1798     * @throws IOException          if an I/O error occurs.
1799     * @since 2.2
1800     */
1801    public static long copyLarge(final InputStream input, final OutputStream output,
1802                                 final long inputOffset, final long length, final byte[] buffer) throws IOException {
1803        if (inputOffset > 0) {
1804            skipFully(input, inputOffset);
1805        }
1806        if (length == 0) {
1807            return 0;
1808        }
1809        final int bufferLength = buffer.length;
1810        int bytesToRead = bufferLength;
1811        if (length > 0 && length < bufferLength) {
1812            bytesToRead = (int) length;
1813        }
1814        int read;
1815        long totalRead = 0;
1816        while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) {
1817            output.write(buffer, 0, read);
1818            totalRead += read;
1819            if (length > 0) { // only adjust length if not reading to the end
1820                // Note the cast must work because buffer.length is an integer
1821                bytesToRead = (int) Math.min(length - totalRead, bufferLength);
1822            }
1823        }
1824        return totalRead;
1825    }
1826
1827    /**
1828     * Copies chars from a large (over 2GB) {@link Reader} to a {@link Writer}.
1829     * <p>
1830     * This method buffers the input internally, so there is no need to use a
1831     * {@link BufferedReader}.
1832     * </p>
1833     * <p>
1834     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1835     * </p>
1836     *
1837     * @param reader the {@link Reader} to source.
1838     * @param writer the {@link Writer} to target.
1839     * @return the number of characters copied.
1840     * @throws NullPointerException if the input or output is null.
1841     * @throws IOException          if an I/O error occurs.
1842     * @since 1.3
1843     */
1844    public static long copyLarge(final Reader reader, final Writer writer) throws IOException {
1845        try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
1846            return copyLarge(reader, writer, scratch.array());
1847        }
1848    }
1849
1850    /**
1851     * Copies chars from a large (over 2GB) {@link Reader} to a {@link Writer}.
1852     * <p>
1853     * This method uses the provided buffer, so there is no need to use a
1854     * {@link BufferedReader}.
1855     * </p>
1856     *
1857     * @param reader the {@link Reader} to source.
1858     * @param writer the {@link Writer} to target.
1859     * @param buffer the buffer to be used for the copy
1860     * @return the number of characters copied
1861     * @throws NullPointerException if the input or output is null
1862     * @throws IOException          if an I/O error occurs
1863     * @since 2.2
1864     */
1865    public static long copyLarge(final Reader reader, final Writer writer, final char[] buffer) throws IOException {
1866        long count = 0;
1867        int n;
1868        while (EOF != (n = reader.read(buffer))) {
1869            writer.write(buffer, 0, n);
1870            count += n;
1871        }
1872        return count;
1873    }
1874
1875    /**
1876     * Copies some or all chars from a large (over 2GB) {@link InputStream} to an {@link OutputStream}, optionally skipping input chars.
1877     * <p>
1878     * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
1879     * </p>
1880     * <p>
1881     * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
1882     * </p>
1883     *
1884     * @param reader      the {@link Reader} to read.
1885     * @param writer      the {@link Writer} to write to.
1886     * @param inputOffset number of chars to skip from input before copying -ve values are ignored.
1887     * @param length      number of chars to copy. -ve means all.
1888     * @return the number of chars copied.
1889     * @throws NullPointerException if the input or output is null.
1890     * @throws IOException          if an I/O error occurs.
1891     * @since 2.2
1892     */
1893    public static long copyLarge(final Reader reader, final Writer writer, final long inputOffset, final long length) throws IOException {
1894        try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
1895            return copyLarge(reader, writer, inputOffset, length, scratch.array());
1896        }
1897    }
1898
1899    /**
1900     * Copies some or all chars from a large (over 2GB) {@link InputStream} to an {@link OutputStream}, optionally skipping input chars.
1901     * <p>
1902     * This method uses the provided buffer, so there is no need to use a {@link BufferedReader}.
1903     * </p>
1904     *
1905     * @param reader      the {@link Reader} to read.
1906     * @param writer      the {@link Writer} to write to.
1907     * @param inputOffset number of chars to skip from input before copying -ve values are ignored.
1908     * @param length      number of chars to copy. -ve means all.
1909     * @param buffer      the buffer to be used for the copy.
1910     * @return the number of chars copied.
1911     * @throws NullPointerException if the input or output is null.
1912     * @throws IOException          if an I/O error occurs.
1913     * @since 2.2
1914     */
1915    public static long copyLarge(final Reader reader, final Writer writer, final long inputOffset, final long length, final char[] buffer) throws IOException {
1916        if (inputOffset > 0) {
1917            skipFully(reader, inputOffset);
1918        }
1919        if (length == 0) {
1920            return 0;
1921        }
1922        int bytesToRead = buffer.length;
1923        if (length > 0 && length < buffer.length) {
1924            bytesToRead = (int) length;
1925        }
1926        int read;
1927        long totalRead = 0;
1928        while (bytesToRead > 0 && EOF != (read = reader.read(buffer, 0, bytesToRead))) {
1929            writer.write(buffer, 0, read);
1930            totalRead += read;
1931            if (length > 0) { // only adjust length if not reading to the end
1932                // Note the cast must work because buffer.length is an integer
1933                bytesToRead = (int) Math.min(length - totalRead, buffer.length);
1934            }
1935        }
1936        return totalRead;
1937    }
1938
1939    /**
1940     * Copies up to {@code size} bytes from the given {@link InputStream} into a new {@link UnsynchronizedByteArrayOutputStream}.
1941     *
1942     * @param input      The {@link InputStream} to read; must not be {@code null}.
1943     * @param limit      The maximum number of bytes to read; must be {@code >= 0}.
1944     *                   The actual bytes read are validated to equal {@code size}.
1945     * @param bufferSize The buffer size of the output stream; must be {@code > 0}.
1946     * @return a ByteArrayOutputStream containing the read bytes.
1947     */
1948    static UnsynchronizedByteArrayOutputStream copyToOutputStream(
1949            final InputStream input, final long limit, final int bufferSize) throws IOException {
1950        try (UnsynchronizedByteArrayOutputStream output = UnsynchronizedByteArrayOutputStream.builder()
1951                        .setBufferSize(bufferSize)
1952                        .get();
1953                InputStream boundedInput = BoundedInputStream.builder()
1954                        .setMaxCount(limit)
1955                        .setPropagateClose(false)
1956                        .setInputStream(input)
1957                        .get()) {
1958            output.write(boundedInput);
1959            return output;
1960        }
1961    }
1962
1963    /**
1964     * Returns the length of the given array in a null-safe manner.
1965     *
1966     * @param array an array or null.
1967     * @return the array length, or 0 if the given array is null.
1968     * @since 2.7
1969     */
1970    public static int length(final byte[] array) {
1971        return array == null ? 0 : array.length;
1972    }
1973
1974    /**
1975     * Returns the length of the given array in a null-safe manner.
1976     *
1977     * @param array an array or null.
1978     * @return the array length, or 0 if the given array is null.
1979     * @since 2.7
1980     */
1981    public static int length(final char[] array) {
1982        return array == null ? 0 : array.length;
1983    }
1984
1985    /**
1986     * Returns the length of the given CharSequence in a null-safe manner.
1987     *
1988     * @param csq a CharSequence or null.
1989     * @return the CharSequence length, or 0 if the given CharSequence is null.
1990     * @since 2.7
1991     */
1992    public static int length(final CharSequence csq) {
1993        return csq == null ? 0 : csq.length();
1994    }
1995
1996    /**
1997     * Returns the length of the given array in a null-safe manner.
1998     *
1999     * @param array an array or null.
2000     * @return the array length, or 0 if the given array is null.
2001     * @since 2.7
2002     */
2003    public static int length(final Object[] array) {
2004        return array == null ? 0 : array.length;
2005    }
2006
2007    /**
2008     * Returns an Iterator for the lines in an {@link InputStream}, using
2009     * the character encoding specified (or default encoding if null).
2010     * <p>
2011     * {@link LineIterator} holds a reference to the open
2012     * {@link InputStream} specified here. When you have finished with
2013     * the iterator you should close the stream to free internal resources.
2014     * This can be done by using a try-with-resources block, closing the stream directly, or by calling
2015     * {@link LineIterator#close()}.
2016     * </p>
2017     * <p>
2018     * The recommended usage pattern is:
2019     * </p>
2020     * <pre>
2021     * try {
2022     *   LineIterator it = IOUtils.lineIterator(stream, charset);
2023     *   while (it.hasNext()) {
2024     *     String line = it.nextLine();
2025     *     /// do something with line
2026     *   }
2027     * } finally {
2028     *   IOUtils.closeQuietly(stream);
2029     * }
2030     * </pre>
2031     *
2032     * @param input the {@link InputStream} to read, not null.
2033     * @param charset the charset to use, null means platform default.
2034     * @return an Iterator of the lines in the reader, never null.
2035     * @throws IllegalArgumentException if the input is null.
2036     * @since 2.3
2037     */
2038    public static LineIterator lineIterator(final InputStream input, final Charset charset) {
2039        return new LineIterator(new InputStreamReader(input, Charsets.toCharset(charset)));
2040    }
2041
2042    /**
2043     * Returns an Iterator for the lines in an {@link InputStream}, using
2044     * the character encoding specified (or default encoding if null).
2045     * <p>
2046     * {@link LineIterator} holds a reference to the open
2047     * {@link InputStream} specified here. When you have finished with
2048     * the iterator you should close the stream to free internal resources.
2049     * This can be done by using a try-with-resources block, closing the stream directly, or by calling
2050     * {@link LineIterator#close()}.
2051     * </p>
2052     * <p>
2053     * The recommended usage pattern is:
2054     * </p>
2055     * <pre>
2056     * try {
2057     *   LineIterator it = IOUtils.lineIterator(stream, StandardCharsets.UTF_8.name());
2058     *   while (it.hasNext()) {
2059     *     String line = it.nextLine();
2060     *     /// do something with line
2061     *   }
2062     * } finally {
2063     *   IOUtils.closeQuietly(stream);
2064     * }
2065     * </pre>
2066     *
2067     * @param input the {@link InputStream} to read, not null.
2068     * @param charsetName the encoding to use, null means platform default.
2069     * @return an Iterator of the lines in the reader, never null.
2070     * @throws IllegalArgumentException                     if the input is null.
2071     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
2072     * @since 1.2
2073     */
2074    public static LineIterator lineIterator(final InputStream input, final String charsetName) {
2075        return lineIterator(input, Charsets.toCharset(charsetName));
2076    }
2077
2078    /**
2079     * Returns an Iterator for the lines in a {@link Reader}.
2080     * <p>
2081     * {@link LineIterator} holds a reference to the open
2082     * {@link Reader} specified here. When you have finished with the
2083     * iterator you should close the reader to free internal resources.
2084     * This can be done by using a try-with-resources block, closing the reader directly, or by calling
2085     * {@link LineIterator#close()}.
2086     * </p>
2087     * <p>
2088     * The recommended usage pattern is:
2089     * </p>
2090     * <pre>
2091     * try {
2092     *   LineIterator it = IOUtils.lineIterator(reader);
2093     *   while (it.hasNext()) {
2094     *     String line = it.nextLine();
2095     *     /// do something with line
2096     *   }
2097     * } finally {
2098     *   IOUtils.closeQuietly(reader);
2099     * }
2100     * </pre>
2101     *
2102     * @param reader the {@link Reader} to read, not null.
2103     * @return an Iterator of the lines in the reader, never null.
2104     * @throws NullPointerException if the reader is null.
2105     * @since 1.2
2106     */
2107    public static LineIterator lineIterator(final Reader reader) {
2108        return new LineIterator(reader);
2109    }
2110
2111    /**
2112     * Reads bytes from an input stream.
2113     * <p>
2114     * This implementation guarantees that it will read as many bytes
2115     * as possible before giving up; this may not always be the case for
2116     * subclasses of {@link InputStream}.
2117     * </p>
2118     *
2119     * @param input where to read input from.
2120     * @param buffer destination.
2121     * @return actual length read; may be less than requested if EOF was reached.
2122     * @throws NullPointerException if {@code input} or {@code buffer} is null.
2123     * @throws IOException if a read error occurs.
2124     * @since 2.2
2125     */
2126    public static int read(final InputStream input, final byte[] buffer) throws IOException {
2127        return read(input, buffer, 0, buffer.length);
2128    }
2129
2130    /**
2131     * Reads bytes from an input stream.
2132     * <p>
2133     * This implementation guarantees that it will read as many bytes
2134     * as possible before giving up; this may not always be the case for
2135     * subclasses of {@link InputStream}.
2136     * </p>
2137     *
2138     * @param input where to read input.
2139     * @param buffer destination.
2140     * @param offset initial offset into buffer.
2141     * @param length length to read, must be &gt;= 0.
2142     * @return actual length read; may be less than requested if EOF was reached.
2143     * @throws NullPointerException     if {@code input} or {@code buffer} is null.
2144     * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if
2145     *                                   {@code offset + length} is greater than {@code buffer.length}.
2146     * @throws IOException              if a read error occurs.
2147     * @since 2.2
2148     */
2149    public static int read(final InputStream input, final byte[] buffer, final int offset, final int length)
2150            throws IOException {
2151        checkFromIndexSize(buffer, offset, length);
2152        int remaining = length;
2153        while (remaining > 0) {
2154            final int location = length - remaining;
2155            final int count = input.read(buffer, offset + location, remaining);
2156            if (EOF == count) {
2157                break;
2158            }
2159            remaining -= count;
2160        }
2161        return length - remaining;
2162    }
2163
2164    /**
2165     * Reads bytes from a ReadableByteChannel.
2166     * <p>
2167     * This implementation guarantees that it will read as many bytes
2168     * as possible before giving up; this may not always be the case for
2169     * subclasses of {@link ReadableByteChannel}.
2170     * </p>
2171     *
2172     * @param input the byte channel to read.
2173     * @param buffer byte buffer destination.
2174     * @return the actual length read; may be less than requested if EOF was reached.
2175     * @throws IOException if a read error occurs.
2176     * @since 2.5
2177     */
2178    public static int read(final ReadableByteChannel input, final ByteBuffer buffer) throws IOException {
2179        final int length = buffer.remaining();
2180        while (buffer.remaining() > 0) {
2181            final int count = input.read(buffer);
2182            if (EOF == count) { // EOF
2183                break;
2184            }
2185        }
2186        return length - buffer.remaining();
2187    }
2188
2189    /**
2190     * Reads characters from an input character stream.
2191     * <p>
2192     * This implementation guarantees that it will read as many characters
2193     * as possible before giving up; this may not always be the case for
2194     * subclasses of {@link Reader}.
2195     * </p>
2196     *
2197     * @param reader where to read input from.
2198     * @param buffer destination.
2199     * @return actual length read; may be less than requested if EOF was reached.
2200     * @throws IOException if a read error occurs.
2201     * @since 2.2
2202     */
2203    public static int read(final Reader reader, final char[] buffer) throws IOException {
2204        return read(reader, buffer, 0, buffer.length);
2205    }
2206
2207    /**
2208     * Reads characters from an input character stream.
2209     * <p>
2210     * This implementation guarantees that it will read as many characters
2211     * as possible before giving up; this may not always be the case for
2212     * subclasses of {@link Reader}.
2213     * </p>
2214     *
2215     * @param reader where to read input from.
2216     * @param buffer destination.
2217     * @param offset initial offset into buffer.
2218     * @param length length to read, must be &gt;= 0.
2219     * @return actual length read; may be less than requested if EOF was reached.
2220     * @throws NullPointerException     if {@code reader} or {@code buffer} is null.
2221     * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if
2222     *                                   {@code offset + length} is greater than {@code buffer.length}.
2223     * @throws IOException              if a read error occurs.
2224     * @since 2.2
2225     */
2226    public static int read(final Reader reader, final char[] buffer, final int offset, final int length)
2227            throws IOException {
2228        checkFromIndexSize(buffer, offset, length);
2229        int remaining = length;
2230        while (remaining > 0) {
2231            final int location = length - remaining;
2232            final int count = reader.read(buffer, offset + location, remaining);
2233            if (EOF == count) { // EOF
2234                break;
2235            }
2236            remaining -= count;
2237        }
2238        return length - remaining;
2239    }
2240
2241    /**
2242     * Reads the requested number of bytes or fail if there are not enough left.
2243     * <p>
2244     * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
2245     * not read as many bytes as requested (most likely because of reaching EOF).
2246     * </p>
2247     *
2248     * @param input where to read input from.
2249     * @param buffer destination.
2250     * @throws NullPointerException     if {@code input} or {@code buffer} is null.
2251     * @throws EOFException             if the number of bytes read was incorrect.
2252     * @throws IOException              if there is a problem reading the file.
2253     * @since 2.2
2254     */
2255    public static void readFully(final InputStream input, final byte[] buffer) throws IOException {
2256        readFully(input, buffer, 0, buffer.length);
2257    }
2258
2259    /**
2260     * Reads the requested number of bytes or fail if there are not enough left.
2261     * <p>
2262     * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
2263     * not read as many bytes as requested (most likely because of reaching EOF).
2264     * </p>
2265     *
2266     * @param input where to read input from.
2267     * @param buffer destination.
2268     * @param offset initial offset into buffer.
2269     * @param length length to read, must be &gt;= 0.
2270     * @throws NullPointerException     if {@code input} or {@code buffer} is null.
2271     * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if
2272     *                                   {@code offset + length} is greater than {@code buffer.length}.
2273     * @throws EOFException             if the number of bytes read was incorrect.
2274     * @throws IOException              if there is a problem reading the file.
2275     * @since 2.2
2276     */
2277    public static void readFully(final InputStream input, final byte[] buffer, final int offset, final int length)
2278            throws IOException {
2279        final int actual = read(input, buffer, offset, length);
2280        if (actual != length) {
2281            throw new EOFException("Length to read: " + length + " actual: " + actual);
2282        }
2283    }
2284
2285    /**
2286     * Reads the requested number of bytes or fail if there are not enough left.
2287     * <p>
2288     * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
2289     * not read as many bytes as requested (most likely because of reaching EOF).
2290     * </p>
2291     *
2292     * @param input where to read input from.
2293     * @param length length to read, must be &gt;= 0.
2294     * @return the bytes read from input.
2295     * @throws IOException              if there is a problem reading the file.
2296     * @throws IllegalArgumentException if length is negative.
2297     * @throws EOFException             if the number of bytes read was incorrect.
2298     * @since 2.5
2299     * @deprecated Use {@link #toByteArray(InputStream, int)}.
2300     */
2301    @Deprecated
2302    public static byte[] readFully(final InputStream input, final int length) throws IOException {
2303        return toByteArray(input, length);
2304    }
2305
2306    /**
2307     * Reads the requested number of bytes or fail if there are not enough left.
2308     * <p>
2309     * This allows for the possibility that {@link ReadableByteChannel#read(ByteBuffer)} may
2310     * not read as many bytes as requested (most likely because of reaching EOF).
2311     * </p>
2312     *
2313     * @param input the byte channel to read.
2314     * @param buffer byte buffer destination.
2315     * @throws IOException  if there is a problem reading the file.
2316     * @throws EOFException if the number of bytes read was incorrect.
2317     * @since 2.5
2318     */
2319    public static void readFully(final ReadableByteChannel input, final ByteBuffer buffer) throws IOException {
2320        final int expected = buffer.remaining();
2321        final int actual = read(input, buffer);
2322        if (actual != expected) {
2323            throw new EOFException("Length to read: " + expected + " actual: " + actual);
2324        }
2325    }
2326
2327    /**
2328     * Reads the requested number of characters or fail if there are not enough left.
2329     * <p>
2330     * This allows for the possibility that {@link Reader#read(char[], int, int)} may
2331     * not read as many characters as requested (most likely because of reaching EOF).
2332     * </p>
2333     *
2334     * @param reader where to read input from.
2335     * @param buffer destination.
2336     * @throws NullPointerException     if {@code reader} or {@code buffer} is null.
2337     * @throws EOFException             if the number of characters read was incorrect.
2338     * @throws IOException              if there is a problem reading the file.
2339     * @since 2.2
2340     */
2341    public static void readFully(final Reader reader, final char[] buffer) throws IOException {
2342        readFully(reader, buffer, 0, buffer.length);
2343    }
2344
2345    /**
2346     * Reads the requested number of characters or fail if there are not enough left.
2347     * <p>
2348     * This allows for the possibility that {@link Reader#read(char[], int, int)} may
2349     * not read as many characters as requested (most likely because of reaching EOF).
2350     * </p>
2351     *
2352     * @param reader where to read input from.
2353     * @param buffer destination.
2354     * @param offset initial offset into buffer.
2355     * @param length length to read, must be &gt;= 0.
2356     * @throws NullPointerException     if {@code reader} or {@code buffer} is null.
2357     * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if
2358     *                                   {@code offset + length} is greater than {@code buffer.length}.
2359     * @throws EOFException             if the number of characters read was incorrect.
2360     * @throws IOException              if there is a problem reading the file.
2361     * @since 2.2
2362     */
2363    public static void readFully(final Reader reader, final char[] buffer, final int offset, final int length)
2364            throws IOException {
2365        final int actual = read(reader, buffer, offset, length);
2366        if (actual != length) {
2367            throw new EOFException("Length to read: " + length + " actual: " + actual);
2368        }
2369    }
2370
2371    /**
2372     * Gets the contents of a {@link CharSequence} as a list of Strings, one entry per line.
2373     *
2374     * @param csq the {@link CharSequence} to read, not null.
2375     * @return the list of Strings, never null.
2376     * @throws UncheckedIOException if an I/O error occurs.
2377     * @since 2.18.0
2378     */
2379    public static List<String> readLines(final CharSequence csq) throws UncheckedIOException {
2380        try (CharSequenceReader reader = new CharSequenceReader(csq)) {
2381            return readLines(reader);
2382        }
2383    }
2384
2385    /**
2386     * Gets the contents of an {@link InputStream} as a list of Strings,
2387     * one entry per line, using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
2388     * <p>
2389     * This method buffers the input internally, so there is no need to use a
2390     * {@link BufferedInputStream}.
2391     * </p>
2392     *
2393     * @param input the {@link InputStream} to read, not null.
2394     * @return the list of Strings, never null.
2395     * @throws NullPointerException if the input is null.
2396     * @throws UncheckedIOException if an I/O error occurs.
2397     * @since 1.1
2398     * @deprecated Use {@link #readLines(InputStream, Charset)} instead
2399     */
2400    @Deprecated
2401    public static List<String> readLines(final InputStream input) throws UncheckedIOException {
2402        return readLines(input, Charset.defaultCharset());
2403    }
2404
2405    /**
2406     * Gets the contents of an {@link InputStream} as a list of Strings,
2407     * one entry per line, using the specified character encoding.
2408     * <p>
2409     * This method buffers the input internally, so there is no need to use a
2410     * {@link BufferedInputStream}.
2411     * </p>
2412     *
2413     * @param input the {@link InputStream} to read, not null.
2414     * @param charset the charset to use, null means platform default.
2415     * @return the list of Strings, never null.
2416     * @throws NullPointerException if the input is null.
2417     * @throws UncheckedIOException if an I/O error occurs.
2418     * @since 2.3
2419     */
2420    public static List<String> readLines(final InputStream input, final Charset charset) throws UncheckedIOException {
2421        return readLines(new InputStreamReader(input, Charsets.toCharset(charset)));
2422    }
2423
2424    /**
2425     * Gets the contents of an {@link InputStream} as a list of Strings,
2426     * one entry per line, using the specified character encoding.
2427     * <p>
2428     * Character encoding names can be found at
2429     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
2430     * </p>
2431     * <p>
2432     * This method buffers the input internally, so there is no need to use a
2433     * {@link BufferedInputStream}.
2434     * </p>
2435     *
2436     * @param input the {@link InputStream} to read, not null.
2437     * @param charsetName the name of the requested charset, null means platform default.
2438     * @return the list of Strings, never null.
2439     * @throws NullPointerException                         if the input is null.
2440     * @throws UncheckedIOException                         if an I/O error occurs.
2441     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
2442     * @since 1.1
2443     */
2444    public static List<String> readLines(final InputStream input, final String charsetName) throws UncheckedIOException {
2445        return readLines(input, Charsets.toCharset(charsetName));
2446    }
2447
2448    /**
2449     * Gets the contents of a {@link Reader} as a list of Strings,
2450     * one entry per line.
2451     * <p>
2452     * This method buffers the input internally, so there is no need to use a
2453     * {@link BufferedReader}.
2454     * </p>
2455     *
2456     * @param reader the {@link Reader} to read, not null.
2457     * @return the list of Strings, never null.
2458     * @throws NullPointerException if the input is null.
2459     * @throws UncheckedIOException if an I/O error occurs.
2460     * @since 1.1
2461     */
2462    @SuppressWarnings("resource") // reader wraps input and is the responsibility of the caller.
2463    public static List<String> readLines(final Reader reader) throws UncheckedIOException {
2464        return toBufferedReader(reader).lines().collect(Collectors.toList());
2465    }
2466
2467    /**
2468     * Gets the contents of a resource as a byte array.
2469     * <p>
2470     * Delegates to {@link #resourceToByteArray(String, ClassLoader) resourceToByteArray(String, null)}.
2471     * </p>
2472     *
2473     * @param name The resource name.
2474     * @return the requested byte array.
2475     * @throws IOException if an I/O error occurs or the resource is not found.
2476     * @see #resourceToByteArray(String, ClassLoader)
2477     * @since 2.6
2478     */
2479    public static byte[] resourceToByteArray(final String name) throws IOException {
2480        return resourceToByteArray(name, null);
2481    }
2482
2483    /**
2484     * Gets the contents of a resource as a byte array.
2485     * <p>
2486     * Delegates to {@link #resourceToURL(String, ClassLoader)}.
2487     * </p>
2488     *
2489     * @param name The resource name.
2490     * @param classLoader the class loader that the resolution of the resource is delegated to.
2491     * @return the requested byte array.
2492     * @throws IOException if an I/O error occurs or the resource is not found.
2493     * @see #resourceToURL(String, ClassLoader)
2494     * @since 2.6
2495     */
2496    public static byte[] resourceToByteArray(final String name, final ClassLoader classLoader) throws IOException {
2497        return toByteArray(resourceToURL(name, classLoader));
2498    }
2499
2500    /**
2501     * Gets the contents of a resource as a String using the specified character encoding.
2502     * <p>
2503     * Delegates to {@link #resourceToString(String, Charset, ClassLoader) resourceToString(String, Charset, null)}.
2504     * </p>
2505     *
2506     * @param name The resource name.
2507     * @param charset the charset to use, null means platform default.
2508     * @return the requested String.
2509     * @throws IOException if an I/O error occurs or the resource is not found.
2510     * @see #resourceToString(String, Charset, ClassLoader)
2511     * @since 2.6
2512     */
2513    public static String resourceToString(final String name, final Charset charset) throws IOException {
2514        return resourceToString(name, charset, null);
2515    }
2516
2517    /**
2518     * Gets the contents of a resource as a String using the specified character encoding.
2519     * <p>
2520     * Delegates to {@link #resourceToURL(String, ClassLoader)}.
2521     * </p>
2522     *
2523     * @param name The resource name.
2524     * @param charset the Charset to use, null means platform default.
2525     * @param classLoader the class loader that the resolution of the resource is delegated to.
2526     * @return the requested String.
2527     * @throws IOException if an I/O error occurs.
2528     * @see #resourceToURL(String, ClassLoader)
2529     * @since 2.6
2530     */
2531    public static String resourceToString(final String name, final Charset charset, final ClassLoader classLoader) throws IOException {
2532        return toString(resourceToURL(name, classLoader), charset);
2533    }
2534
2535    /**
2536     * Gets a URL pointing to the given resource.
2537     * <p>
2538     * Delegates to {@link #resourceToURL(String, ClassLoader) resourceToURL(String, null)}.
2539     * </p>
2540     *
2541     * @param name The resource name.
2542     * @return A URL object for reading the resource.
2543     * @throws IOException if the resource is not found.
2544     * @since 2.6
2545     */
2546    public static URL resourceToURL(final String name) throws IOException {
2547        return resourceToURL(name, null);
2548    }
2549
2550    /**
2551     * Gets a URL pointing to the given resource.
2552     * <p>
2553     * If the {@code classLoader} is not null, call {@link ClassLoader#getResource(String)}, otherwise call
2554     * {@link Class#getResource(String) IOUtils.class.getResource(name)}.
2555     * </p>
2556     *
2557     * @param name The resource name.
2558     * @param classLoader Delegate to this class loader if not null.
2559     * @return A URL object for reading the resource.
2560     * @throws IOException if the resource is not found.
2561     * @since 2.6
2562     */
2563    public static URL resourceToURL(final String name, final ClassLoader classLoader) throws IOException {
2564        // What about the thread context class loader?
2565        // What about the system class loader?
2566        final URL resource = classLoader == null ? IOUtils.class.getResource(name) : classLoader.getResource(name);
2567        if (resource == null) {
2568            throw new IOException("Resource not found: " + name);
2569        }
2570        return resource;
2571    }
2572
2573    /**
2574     * Skips bytes from an input byte stream.
2575     * <p>
2576     * This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case for skip() implementations
2577     * in subclasses of {@link InputStream}.
2578     * </p>
2579     * <p>
2580     * Note that the implementation uses {@link InputStream#read(byte[], int, int)} rather than delegating to {@link InputStream#skip(long)}. This means that
2581     * the method may be considerably less efficient than using the actual skip implementation, this is done to guarantee that the correct number of bytes are
2582     * skipped.
2583     * </p>
2584     *
2585     * @param input byte stream to skip.
2586     * @param skip  number of bytes to skip.
2587     * @return number of bytes actually skipped.
2588     * @throws IOException              if there is a problem reading the file.
2589     * @throws IllegalArgumentException if toSkip is negative.
2590     * @see InputStream#skip(long)
2591     * @see <a href="https://issues.apache.org/jira/browse/IO-203">IO-203 - Add skipFully() method for InputStreams</a>
2592     * @since 2.0
2593     */
2594    public static long skip(final InputStream input, final long skip) throws IOException {
2595        try (ScratchBytes scratch = ScratchBytes.get()) {
2596            return skip(input, skip, scratch::array);
2597        }
2598    }
2599
2600    /**
2601     * Skips bytes from an input byte stream.
2602     * <p>
2603     * Intended for special cases when customization of the temporary buffer is needed because, for example, a nested input stream has requirements for the
2604     * bytes read. For example, when using {@link InflaterInputStream}s from multiple threads.
2605     * </p>
2606     * <p>
2607     * This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case for skip() implementations
2608     * in subclasses of {@link InputStream}.
2609     * </p>
2610     * <p>
2611     * Note that the implementation uses {@link InputStream#read(byte[], int, int)} rather than delegating to {@link InputStream#skip(long)}. This means that
2612     * the method may be considerably less efficient than using the actual skip implementation, this is done to guarantee that the correct number of bytes are
2613     * skipped.
2614     * </p>
2615     *
2616     * @param input              byte stream to skip.
2617     * @param skip             number of bytes to skip.
2618     * @param skipBufferSupplier Supplies the buffer to use for reading.
2619     * @return number of bytes actually skipped.
2620     * @throws IOException              if there is a problem reading the file.
2621     * @throws IllegalArgumentException if toSkip is negative.
2622     * @see InputStream#skip(long)
2623     * @see <a href="https://issues.apache.org/jira/browse/IO-203">IO-203 - Add skipFully() method for InputStreams</a>
2624     * @since 2.14.0
2625     */
2626    public static long skip(final InputStream input, final long skip, final Supplier<byte[]> skipBufferSupplier) throws IOException {
2627        if (skip < 0) {
2628            throw new IllegalArgumentException("Skip count must be non-negative, actual: " + skip);
2629        }
2630        //
2631        // No need to synchronize access to SCRATCH_BYTE_BUFFER_WO: We don't care if the buffer is written multiple
2632        // times or in parallel since the data is ignored. We reuse the same buffer, if the buffer size were variable or read-write,
2633        // we would need to synch or use a thread local to ensure some other thread safety.
2634        //
2635        long remain = skip;
2636        while (remain > 0) {
2637            final byte[] skipBuffer = skipBufferSupplier.get();
2638            // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip()
2639            final long n = input.read(skipBuffer, 0, (int) Math.min(remain, skipBuffer.length));
2640            if (n < 0) { // EOF
2641                break;
2642            }
2643            remain -= n;
2644        }
2645        return skip - remain;
2646    }
2647
2648    /**
2649     * Skips bytes from a ReadableByteChannel.
2650     * This implementation guarantees that it will read as many bytes
2651     * as possible before giving up.
2652     *
2653     * @param input ReadableByteChannel to skip.
2654     * @param toSkip number of bytes to skip.
2655     * @return number of bytes actually skipped.
2656     * @throws IOException              if there is a problem reading the ReadableByteChannel.
2657     * @throws IllegalArgumentException if toSkip is negative.
2658     * @since 2.5
2659     */
2660    public static long skip(final ReadableByteChannel input, final long toSkip) throws IOException {
2661        if (toSkip < 0) {
2662            throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip);
2663        }
2664        final ByteBuffer skipByteBuffer = ByteBuffer.allocate((int) Math.min(toSkip, DEFAULT_BUFFER_SIZE));
2665        long remain = toSkip;
2666        while (remain > 0) {
2667            skipByteBuffer.position(0);
2668            skipByteBuffer.limit((int) Math.min(remain, DEFAULT_BUFFER_SIZE));
2669            final int n = input.read(skipByteBuffer);
2670            if (n == EOF) {
2671                break;
2672            }
2673            remain -= n;
2674        }
2675        return toSkip - remain;
2676    }
2677
2678    /**
2679     * Skips characters from an input character stream.
2680     * This implementation guarantees that it will read as many characters
2681     * as possible before giving up; this may not always be the case for
2682     * skip() implementations in subclasses of {@link Reader}.
2683     * <p>
2684     * Note that the implementation uses {@link Reader#read(char[], int, int)} rather
2685     * than delegating to {@link Reader#skip(long)}.
2686     * This means that the method may be considerably less efficient than using the actual skip implementation,
2687     * this is done to guarantee that the correct number of characters are skipped.
2688     * </p>
2689     *
2690     * @param reader character stream to skip.
2691     * @param toSkip number of characters to skip.
2692     * @return number of characters actually skipped.
2693     * @throws IOException              if there is a problem reading the file.
2694     * @throws IllegalArgumentException if toSkip is negative.
2695     * @see Reader#skip(long)
2696     * @see <a href="https://issues.apache.org/jira/browse/IO-203">IO-203 - Add skipFully() method for InputStreams</a>
2697     * @since 2.0
2698     */
2699    public static long skip(final Reader reader, final long toSkip) throws IOException {
2700        if (toSkip < 0) {
2701            throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip);
2702        }
2703        long remain = toSkip;
2704        try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
2705            final char[] chars = scratch.array();
2706            while (remain > 0) {
2707                // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip()
2708                final long n = reader.read(chars, 0, (int) Math.min(remain, chars.length));
2709                if (n < 0) { // EOF
2710                    break;
2711                }
2712                remain -= n;
2713            }
2714        }
2715        return toSkip - remain;
2716    }
2717
2718    /**
2719     * Skips the requested number of bytes or fail if there are not enough left.
2720     * <p>
2721     * This allows for the possibility that {@link InputStream#skip(long)} may
2722     * not skip as many bytes as requested (most likely because of reaching EOF).
2723     * </p>
2724     * <p>
2725     * Note that the implementation uses {@link #skip(InputStream, long)}.
2726     * This means that the method may be considerably less efficient than using the actual skip implementation,
2727     * this is done to guarantee that the correct number of characters are skipped.
2728     * </p>
2729     *
2730     * @param input stream to skip.
2731     * @param toSkip the number of bytes to skip.
2732     * @throws IOException              if there is a problem reading the file.
2733     * @throws IllegalArgumentException if toSkip is negative.
2734     * @throws EOFException             if the number of bytes skipped was incorrect.
2735     * @see InputStream#skip(long)
2736     * @since 2.0
2737     */
2738    public static void skipFully(final InputStream input, final long toSkip) throws IOException {
2739        final long skipped = skip(input, toSkip);
2740        if (skipped != toSkip) {
2741            throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped);
2742        }
2743    }
2744
2745    /**
2746     * Skips the requested number of bytes or fail if there are not enough left.
2747     * <p>
2748     * Intended for special cases when customization of the temporary buffer is needed because, for example, a nested input stream has requirements for the
2749     * bytes read. For example, when using {@link InflaterInputStream}s from multiple threads.
2750     * </p>
2751     * <p>
2752     * This allows for the possibility that {@link InputStream#skip(long)} may not skip as many bytes as requested (most likely because of reaching EOF).
2753     * </p>
2754     * <p>
2755     * Note that the implementation uses {@link #skip(InputStream, long)}. This means that the method may be considerably less efficient than using the actual
2756     * skip implementation, this is done to guarantee that the correct number of characters are skipped.
2757     * </p>
2758     *
2759     * @param input              stream to skip.
2760     * @param toSkip             the number of bytes to skip.
2761     * @param skipBufferSupplier Supplies the buffer to use for reading.
2762     * @throws IOException              if there is a problem reading the file.
2763     * @throws IllegalArgumentException if toSkip is negative.
2764     * @throws EOFException             if the number of bytes skipped was incorrect.
2765     * @see InputStream#skip(long)
2766     * @since 2.14.0
2767     */
2768    public static void skipFully(final InputStream input, final long toSkip, final Supplier<byte[]> skipBufferSupplier) throws IOException {
2769        if (toSkip < 0) {
2770            throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip);
2771        }
2772        final long skipped = skip(input, toSkip, skipBufferSupplier);
2773        if (skipped != toSkip) {
2774            throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped);
2775        }
2776    }
2777
2778    /**
2779     * Skips the requested number of bytes or fail if there are not enough left.
2780     *
2781     * @param input ReadableByteChannel to skip.
2782     * @param toSkip the number of bytes to skip.
2783     * @throws IOException              if there is a problem reading the ReadableByteChannel.
2784     * @throws IllegalArgumentException if toSkip is negative.
2785     * @throws EOFException             if the number of bytes skipped was incorrect.
2786     * @since 2.5
2787     */
2788    public static void skipFully(final ReadableByteChannel input, final long toSkip) throws IOException {
2789        if (toSkip < 0) {
2790            throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip);
2791        }
2792        final long skipped = skip(input, toSkip);
2793        if (skipped != toSkip) {
2794            throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped);
2795        }
2796    }
2797
2798    /**
2799     * Skips the requested number of characters or fail if there are not enough left.
2800     * <p>
2801     * This allows for the possibility that {@link Reader#skip(long)} may
2802     * not skip as many characters as requested (most likely because of reaching EOF).
2803     * </p>
2804     * <p>
2805     * Note that the implementation uses {@link #skip(Reader, long)}.
2806     * This means that the method may be considerably less efficient than using the actual skip implementation,
2807     * this is done to guarantee that the correct number of characters are skipped.
2808     * </p>
2809     *
2810     * @param reader stream to skip.
2811     * @param toSkip the number of characters to skip.
2812     * @throws IOException              if there is a problem reading the file.
2813     * @throws IllegalArgumentException if toSkip is negative.
2814     * @throws EOFException             if the number of characters skipped was incorrect.
2815     * @see Reader#skip(long)
2816     * @since 2.0
2817     */
2818    public static void skipFully(final Reader reader, final long toSkip) throws IOException {
2819        final long skipped = skip(reader, toSkip);
2820        if (skipped != toSkip) {
2821            throw new EOFException("Chars to skip: " + toSkip + " actual: " + skipped);
2822        }
2823    }
2824
2825    /**
2826     * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream.
2827     * <p>
2828     * This method is useful where,
2829     * </p>
2830     * <ul>
2831     * <li>Source InputStream is slow.</li>
2832     * <li>It has network resources associated, so we cannot keep it open for long time.</li>
2833     * <li>It has network timeout associated.</li>
2834     * </ul>
2835     * <p>
2836     * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].<br>
2837     * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
2838     * </p>
2839     *
2840     * @param input Stream to be fully buffered.
2841     * @return A fully buffered stream.
2842     * @throws IOException if an I/O error occurs.
2843     * @since 2.0
2844     */
2845    public static InputStream toBufferedInputStream(final InputStream input) throws IOException {
2846        return ByteArrayOutputStream.toBufferedInputStream(input);
2847    }
2848
2849    /**
2850     * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream.
2851     * <p>
2852     * This method is useful where,
2853     * </p>
2854     * <ul>
2855     * <li>Source InputStream is slow.</li>
2856     * <li>It has network resources associated, so we cannot keep it open for long time.</li>
2857     * <li>It has network timeout associated.</li>
2858     * </ul>
2859     * <p>
2860     * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].<br>
2861     * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
2862     * </p>
2863     *
2864     * @param input Stream to be fully buffered.
2865     * @param size  the initial buffer size.
2866     * @return A fully buffered stream.
2867     * @throws IOException if an I/O error occurs.
2868     * @since 2.5
2869     */
2870    public static InputStream toBufferedInputStream(final InputStream input, final int size) throws IOException {
2871        return ByteArrayOutputStream.toBufferedInputStream(input, size);
2872    }
2873
2874    /**
2875     * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
2876     * reader.
2877     *
2878     * @param reader the reader to wrap or return (not null).
2879     * @return the given reader or a new {@link BufferedReader} for the given reader.
2880     * @throws NullPointerException if the input parameter is null.
2881     * @see #buffer(Reader)
2882     * @since 2.2
2883     */
2884    public static BufferedReader toBufferedReader(final Reader reader) {
2885        return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader);
2886    }
2887
2888    /**
2889     * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
2890     * reader.
2891     *
2892     * @param reader the reader to wrap or return (not null).
2893     * @param size the buffer size, if a new BufferedReader is created.
2894     * @return the given reader or a new {@link BufferedReader} for the given reader.
2895     * @throws NullPointerException if the input parameter is null.
2896     * @see #buffer(Reader)
2897     * @since 2.5
2898     */
2899    public static BufferedReader toBufferedReader(final Reader reader, final int size) {
2900        return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader, size);
2901    }
2902
2903    /**
2904     * Reads all the bytes from an input stream in a byte array.
2905     *
2906     * <p>The memory used by this method is <strong>proportional</strong> to the number
2907     * of bytes read, which is only limited by {@link Integer#MAX_VALUE}. Only streams
2908     * which fit into a single byte array with roughly 2 GiB limit can be processed
2909     * with this method.</p>
2910     *
2911     * @param inputStream The {@link InputStream} to read; must not be {@code null}.
2912     * @return A new byte array.
2913     * @throws IOException              If an I/O error occurs while reading or if the maximum array size is exceeded.
2914     * @throws NullPointerException     If {@code inputStream} is {@code null}.
2915     */
2916    public static byte[] toByteArray(final InputStream inputStream) throws IOException {
2917        // Using SOFT_MAX_ARRAY_LENGTH guarantees that size() will not overflow
2918        final UnsynchronizedByteArrayOutputStream output = copyToOutputStream(inputStream, SOFT_MAX_ARRAY_LENGTH + 1, DEFAULT_BUFFER_SIZE);
2919        if (output.size() > SOFT_MAX_ARRAY_LENGTH) {
2920            throw new IOException(String.format("Cannot read more than %,d into a byte array", SOFT_MAX_ARRAY_LENGTH));
2921        }
2922        return output.toByteArray();
2923    }
2924
2925    /**
2926     * Reads exactly {@code size} bytes from the given {@link InputStream} into a new {@code byte[]}.
2927     *
2928     * <p>This variant always allocates the whole requested array size,
2929     * for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)},
2930     * which enforces stricter memory usage constraints.</p>
2931     *
2932     * @param input the {@link InputStream} to read; must not be {@code null}.
2933     * @param size  the exact number of bytes to read; must be {@code >= 0}.
2934     * @return a new byte array of length {@code size}.
2935     * @throws IllegalArgumentException if {@code size} is negative.
2936     * @throws EOFException             if the stream ends before {@code size} bytes are read.
2937     * @throws IOException              if an I/O error occurs while reading.
2938     * @throws NullPointerException     if {@code input} is {@code null}.
2939     * @since 2.1
2940     */
2941    public static byte[] toByteArray(final InputStream input, final int size) throws IOException {
2942        return toByteArray(Objects.requireNonNull(input, "input")::read, size);
2943    }
2944
2945    /**
2946     * Reads exactly {@code size} bytes from the given {@link InputStream} into a new {@code byte[]}.
2947     *
2948     * <p>The memory used by this method is <strong>proportional</strong> to the number
2949     * of bytes read and limited by the specified {@code size}. This makes it suitable for
2950     * processing large input streams, provided that <strong>sufficient</strong> heap space is
2951     * available.</p>
2952     *
2953     * <p>This method processes the input stream in successive chunks of up to
2954     * {@code chunkSize} bytes.</p>
2955     *
2956     * @param input      the {@link InputStream} to read; must not be {@code null}.
2957     * @param size       the exact number of bytes to read; must be {@code >= 0}.
2958     *                   The actual bytes read are validated to equal {@code size}.
2959     * @param chunkSize  The chunk size for incremental reading; must be {@code > 0}.
2960     * @return a new byte array of length {@code size}.
2961     * @throws IllegalArgumentException if {@code size} is negative or {@code chunkSize <= 0}.
2962     * @throws EOFException             if the stream ends before {@code size} bytes are read.
2963     * @throws IOException              if an I/O error occurs while reading.
2964     * @throws NullPointerException     if {@code input} is {@code null}.
2965     * @since 2.21.0
2966     */
2967    public static byte[] toByteArray(final InputStream input, final int size, final int chunkSize) throws IOException {
2968        Objects.requireNonNull(input, "input");
2969        if (chunkSize <= 0) {
2970            throw new IllegalArgumentException(String.format("chunkSize <= 0, chunkSize = %,d", chunkSize));
2971        }
2972        if (size <= chunkSize) {
2973            // throws if size < 0
2974            return toByteArray(input::read, size);
2975        }
2976        final UnsynchronizedByteArrayOutputStream output = copyToOutputStream(input, size, chunkSize);
2977        final int outSize = output.size();
2978        if (outSize != size) {
2979            throw new EOFException(String.format("Expected read size: %,d, actual: %,d", size, outSize));
2980        }
2981        return output.toByteArray();
2982    }
2983
2984    /**
2985     * Reads exactly {@code size} bytes from the given {@link InputStream} into a new {@code byte[]}.
2986     *
2987     * <p>This variant always allocates the whole requested array size,
2988     * for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)},
2989     * which enforces stricter memory usage constraints.</p>
2990     *
2991     * @param input the {@link InputStream} to read; must not be {@code null}.
2992     * @param size  the exact number of bytes to read; must be {@code >= 0} and {@code <= Integer.MAX_VALUE}.
2993     * @return a new byte array of length {@code size}.
2994     * @throws IllegalArgumentException if {@code size} is negative or does not fit into an int.
2995     * @throws EOFException             if the stream ends before {@code size} bytes are read.
2996     * @throws IOException              if an I/O error occurs while reading.
2997     * @throws NullPointerException     if {@code input} is {@code null}.
2998     * @see #toByteArray(InputStream, int, int)
2999     * @since 2.1
3000     */
3001    public static byte[] toByteArray(final InputStream input, final long size) throws IOException {
3002        if (size > Integer.MAX_VALUE) {
3003            throw new IllegalArgumentException(String.format("size > Integer.MAX_VALUE, size = %,d", size));
3004        }
3005        return toByteArray(input, (int) size);
3006    }
3007
3008    /**
3009     * Gets the contents of an input as a {@code byte[]}.
3010     *
3011     * @param input the input to read, not null.
3012     * @param size the size of the input to read, where 0 &lt; {@code size} &lt;= length of input.
3013     * @return byte [] of length {@code size}.
3014     * @throws EOFException if the end of the input is reached before reading {@code size} bytes.
3015     * @throws IOException if an I/O error occurs or input length is smaller than parameter {@code size}.
3016     * @throws IllegalArgumentException if {@code size} is less than zero.
3017     */
3018    static byte[] toByteArray(final IOTriFunction<byte[], Integer, Integer, Integer> input, final int size) throws IOException {
3019        if (size < 0) {
3020            throw new IllegalArgumentException(String.format("size < 0, size = %,d", size));
3021        }
3022        if (size == 0) {
3023            return EMPTY_BYTE_ARRAY;
3024        }
3025        final byte[] data = byteArray(size);
3026        int offset = 0;
3027        int read;
3028        while (offset < size && (read = input.apply(data, offset, size - offset)) != EOF) {
3029            offset += read;
3030        }
3031        if (offset != size) {
3032            throw new EOFException(String.format("Expected read size: %,d, actual: %,d", size, offset));
3033        }
3034        return data;
3035    }
3036
3037    /**
3038     * Gets the contents of a {@link Reader} as a {@code byte[]}
3039     * using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3040     * <p>
3041     * This method buffers the input internally, so there is no need to use a
3042     * {@link BufferedReader}.
3043     * </p>
3044     *
3045     * @param reader the {@link Reader} to read.
3046     * @return the requested byte array.
3047     * @throws NullPointerException if the input is null.
3048     * @throws IOException          if an I/O error occurs.
3049     * @deprecated Use {@link #toByteArray(Reader, Charset)} instead.
3050     */
3051    @Deprecated
3052    public static byte[] toByteArray(final Reader reader) throws IOException {
3053        return toByteArray(reader, Charset.defaultCharset());
3054    }
3055
3056    /**
3057     * Gets the contents of a {@link Reader} as a {@code byte[]}
3058     * using the specified character encoding.
3059     * <p>
3060     * This method buffers the input internally, so there is no need to use a
3061     * {@link BufferedReader}.
3062     * </p>
3063     *
3064     * @param reader the {@link Reader} to read.
3065     * @param charset the charset to use, null means platform default.
3066     * @return the requested byte array.
3067     * @throws NullPointerException if the input is null.
3068     * @throws IOException          if an I/O error occurs.
3069     * @since 2.3
3070     */
3071    public static byte[] toByteArray(final Reader reader, final Charset charset) throws IOException {
3072        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
3073            copy(reader, output, charset);
3074            return output.toByteArray();
3075        }
3076    }
3077
3078    /**
3079     * Gets the contents of a {@link Reader} as a {@code byte[]}
3080     * using the specified character encoding.
3081     * <p>
3082     * Character encoding names can be found at
3083     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3084     * </p>
3085     * <p>
3086     * This method buffers the input internally, so there is no need to use a
3087     * {@link BufferedReader}.
3088     * </p>
3089     *
3090     * @param reader the {@link Reader} to read.
3091     * @param charsetName the name of the requested charset, null means platform default.
3092     * @return the requested byte array.
3093     * @throws NullPointerException                         if the input is null.
3094     * @throws IOException                                  if an I/O error occurs.
3095     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3096     * @since 1.1
3097     */
3098    public static byte[] toByteArray(final Reader reader, final String charsetName) throws IOException {
3099        return toByteArray(reader, Charsets.toCharset(charsetName));
3100    }
3101
3102    /**
3103     * Gets the contents of a {@link String} as a {@code byte[]}
3104     * using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3105     * <p>
3106     * This is the same as {@link String#getBytes()}.
3107     * </p>
3108     *
3109     * @param input the {@link String} to convert.
3110     * @return the requested byte array.
3111     * @throws NullPointerException if the input is null.
3112     * @deprecated Use {@link String#getBytes()} instead.
3113     */
3114    @Deprecated
3115    public static byte[] toByteArray(final String input) {
3116        // make explicit the use of the default charset
3117        return input.getBytes(Charset.defaultCharset());
3118    }
3119
3120    /**
3121     * Gets the contents of a {@link URI} as a {@code byte[]}.
3122     *
3123     * @param uri the {@link URI} to read.
3124     * @return the requested byte array.
3125     * @throws NullPointerException if the uri is null.
3126     * @throws IOException          if an I/O exception occurs.
3127     * @since 2.4
3128     */
3129    public static byte[] toByteArray(final URI uri) throws IOException {
3130        return toByteArray(uri.toURL());
3131    }
3132
3133    /**
3134     * Gets the contents of a {@link URL} as a {@code byte[]}.
3135     *
3136     * @param url the {@link URL} to read.
3137     * @return the requested byte array.
3138     * @throws NullPointerException if the input is null.
3139     * @throws IOException          if an I/O exception occurs.
3140     * @since 2.4
3141     */
3142    public static byte[] toByteArray(final URL url) throws IOException {
3143        try (CloseableURLConnection urlConnection = CloseableURLConnection.open(url)) {
3144            return toByteArray(urlConnection);
3145        }
3146    }
3147
3148    /**
3149     * Gets the contents of a {@link URLConnection} as a {@code byte[]}.
3150     *
3151     * @param urlConnection the {@link URLConnection} to read.
3152     * @return the requested byte array.
3153     * @throws NullPointerException if the urlConn is null.
3154     * @throws IOException if an I/O exception occurs.
3155     * @since 2.4
3156     */
3157    public static byte[] toByteArray(final URLConnection urlConnection) throws IOException {
3158        try (InputStream inputStream = urlConnection.getInputStream()) {
3159            return toByteArray(inputStream);
3160        }
3161    }
3162
3163    /**
3164     * Gets the contents of an {@link InputStream} as a character array
3165     * using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3166     * <p>
3167     * This method buffers the input internally, so there is no need to use a
3168     * {@link BufferedInputStream}.
3169     * </p>
3170     *
3171     * @param inputStream the {@link InputStream} to read.
3172     * @return the requested character array.
3173     * @throws NullPointerException if the input is null.
3174     * @throws IOException          if an I/O error occurs.
3175     * @since 1.1
3176     * @deprecated Use {@link #toCharArray(InputStream, Charset)} instead
3177     */
3178    @Deprecated
3179    public static char[] toCharArray(final InputStream inputStream) throws IOException {
3180        return toCharArray(inputStream, Charset.defaultCharset());
3181    }
3182
3183    /**
3184     * Gets the contents of an {@link InputStream} as a character array
3185     * using the specified character encoding.
3186     * <p>
3187     * This method buffers the input internally, so there is no need to use a
3188     * {@link BufferedInputStream}.
3189     * </p>
3190     *
3191     * @param inputStream the {@link InputStream} to read.
3192     * @param charset the charset to use, null means platform default.
3193     * @return the requested character array.
3194     * @throws NullPointerException if the input is null.
3195     * @throws IOException          if an I/O error occurs.
3196     * @since 2.3
3197     */
3198    public static char[] toCharArray(final InputStream inputStream, final Charset charset)
3199            throws IOException {
3200        final CharArrayWriter writer = new CharArrayWriter();
3201        copy(inputStream, writer, charset);
3202        return writer.toCharArray();
3203    }
3204
3205    /**
3206     * Gets the contents of an {@link InputStream} as a character array
3207     * using the specified character encoding.
3208     * <p>
3209     * Character encoding names can be found at
3210     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3211     * </p>
3212     * <p>
3213     * This method buffers the input internally, so there is no need to use a
3214     * {@link BufferedInputStream}.
3215     * </p>
3216     *
3217     * @param inputStream the {@link InputStream} to read.
3218     * @param charsetName the name of the requested charset, null means platform default.
3219     * @return the requested character array.
3220     * @throws NullPointerException                         if the input is null.
3221     * @throws IOException                                  if an I/O error occurs.
3222     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3223     * @since 1.1
3224     */
3225    public static char[] toCharArray(final InputStream inputStream, final String charsetName) throws IOException {
3226        return toCharArray(inputStream, Charsets.toCharset(charsetName));
3227    }
3228
3229    /**
3230     * Gets the contents of a {@link Reader} as a character array.
3231     * <p>
3232     * This method buffers the input internally, so there is no need to use a
3233     * {@link BufferedReader}.
3234     * </p>
3235     *
3236     * @param reader the {@link Reader} to read.
3237     * @return the requested character array.
3238     * @throws NullPointerException if the input is null.
3239     * @throws IOException          if an I/O error occurs.
3240     * @since 1.1
3241     */
3242    public static char[] toCharArray(final Reader reader) throws IOException {
3243        final CharArrayWriter sw = new CharArrayWriter();
3244        copy(reader, sw);
3245        return sw.toCharArray();
3246    }
3247
3248    /**
3249     * Converts the specified CharSequence to an input stream, encoded as bytes
3250     * using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3251     *
3252     * @param input the CharSequence to convert.
3253     * @return an input stream.
3254     * @since 2.0
3255     * @deprecated Use {@link #toInputStream(CharSequence, Charset)} instead.
3256     */
3257    @Deprecated
3258    public static InputStream toInputStream(final CharSequence input) {
3259        return toInputStream(input, Charset.defaultCharset());
3260    }
3261
3262    /**
3263     * Converts the specified CharSequence to an input stream, encoded as bytes
3264     * using the specified character encoding.
3265     *
3266     * @param input the CharSequence to convert.
3267     * @param charset the charset to use, null means platform default.
3268     * @return an input stream.
3269     * @since 2.3
3270     */
3271    public static InputStream toInputStream(final CharSequence input, final Charset charset) {
3272        return toInputStream(input.toString(), charset);
3273    }
3274
3275    /**
3276     * Converts the specified CharSequence to an input stream, encoded as bytes
3277     * using the specified character encoding.
3278     * <p>
3279     * Character encoding names can be found at
3280     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3281     * </p>
3282     *
3283     * @param input the CharSequence to convert.
3284     * @param charsetName the name of the requested charset, null means platform default.
3285     * @return an input stream.
3286     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3287     * @since 2.0
3288     */
3289    public static InputStream toInputStream(final CharSequence input, final String charsetName) {
3290        return toInputStream(input, Charsets.toCharset(charsetName));
3291    }
3292
3293    /**
3294     * Converts the specified string to an input stream, encoded as bytes
3295     * using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3296     *
3297     * @param input the string to convert.
3298     * @return an input stream.
3299     * @since 1.1
3300     * @deprecated Use {@link #toInputStream(String, Charset)} instead.
3301     */
3302    @Deprecated
3303    public static InputStream toInputStream(final String input) {
3304        return toInputStream(input, Charset.defaultCharset());
3305    }
3306
3307    /**
3308     * Converts the specified string to an input stream, encoded as bytes
3309     * using the specified character encoding.
3310     *
3311     * @param input the string to convert.
3312     * @param charset the charset to use, null means platform default.
3313     * @return an input stream.
3314     * @since 2.3
3315     */
3316    public static InputStream toInputStream(final String input, final Charset charset) {
3317        return new ByteArrayInputStream(input.getBytes(Charsets.toCharset(charset)));
3318    }
3319
3320    /**
3321     * Converts the specified string to an input stream, encoded as bytes
3322     * using the specified character encoding.
3323     * <p>
3324     * Character encoding names can be found at
3325     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3326     * </p>
3327     *
3328     * @param input the string to convert.
3329     * @param charsetName the name of the requested charset, null means platform default.
3330     * @return an input stream.
3331     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3332     * @since 1.1
3333     */
3334    public static InputStream toInputStream(final String input, final String charsetName) {
3335        return new ByteArrayInputStream(input.getBytes(Charsets.toCharset(charsetName)));
3336    }
3337
3338    /**
3339     * Gets the contents of a {@code byte[]} as a String
3340     * using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3341     *
3342     * @param input the byte array to read.
3343     * @return the requested String.
3344     * @throws NullPointerException if the input is null.
3345     * @deprecated Use {@link String#String(byte[])} instead.
3346     */
3347    @Deprecated
3348    public static String toString(final byte[] input) {
3349        // make explicit the use of the default charset
3350        return new String(input, Charset.defaultCharset());
3351    }
3352
3353    /**
3354     * Gets the contents of a {@code byte[]} as a String
3355     * using the specified character encoding.
3356     * <p>
3357     * Character encoding names can be found at
3358     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3359     * </p>
3360     *
3361     * @param input the byte array to read.
3362     * @param charsetName the name of the requested charset, null means platform default.
3363     * @return the requested String.
3364     * @throws NullPointerException if the input is null.
3365     */
3366    public static String toString(final byte[] input, final String charsetName) {
3367        return new String(input, Charsets.toCharset(charsetName));
3368    }
3369
3370    /**
3371     * Gets the contents of an {@link InputStream} as a String
3372     * using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3373     * <p>
3374     * This method buffers the input internally, so there is no need to use a
3375     * {@link BufferedInputStream}.
3376     * </p>
3377     *
3378     * @param input the {@link InputStream} to read.
3379     * @return the requested String.
3380     * @throws NullPointerException if the input is null.
3381     * @throws IOException          if an I/O error occurs.
3382     * @deprecated Use {@link #toString(InputStream, Charset)} instead.
3383     */
3384    @Deprecated
3385    public static String toString(final InputStream input) throws IOException {
3386        return toString(input, Charset.defaultCharset());
3387    }
3388
3389    /**
3390     * Gets the contents of an {@link InputStream} as a String
3391     * using the specified character encoding.
3392     * <p>
3393     * This method buffers the input internally, so there is no need to use a
3394     * {@link BufferedInputStream}.
3395     * </p>
3396     *
3397     * @param input the {@link InputStream} to read.
3398     * @param charset the charset to use, null means platform default.
3399     * @return the requested String.
3400     * @throws NullPointerException if the input is null.
3401     * @throws IOException          if an I/O error occurs.
3402     * @since 2.3
3403     */
3404    public static String toString(final InputStream input, final Charset charset) throws IOException {
3405        try (StringBuilderWriter sw = new StringBuilderWriter()) {
3406            copy(input, sw, charset);
3407            return sw.toString();
3408        }
3409    }
3410
3411    /**
3412     * Gets the contents of an {@link InputStream} as a String
3413     * using the specified character encoding.
3414     * <p>
3415     * Character encoding names can be found at
3416     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3417     * </p>
3418     * <p>
3419     * This method buffers the input internally, so there is no need to use a
3420     * {@link BufferedInputStream}.
3421     * </p>
3422     *
3423     * @param input the {@link InputStream} to read.
3424     * @param charsetName the name of the requested charset, null means platform default.
3425     * @return the requested String.
3426     * @throws NullPointerException                         if the input is null.
3427     * @throws IOException                                  if an I/O error occurs.
3428     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3429     */
3430    public static String toString(final InputStream input, final String charsetName)
3431            throws IOException {
3432        return toString(input, Charsets.toCharset(charsetName));
3433    }
3434
3435    /**
3436     * Gets the contents of an {@link InputStream} from a supplier as a String
3437     * using the specified character encoding.
3438     * <p>
3439     * This method buffers the input internally, so there is no need to use a
3440     * {@link BufferedInputStream}.
3441     * </p>
3442     *
3443     * @param input supplies the {@link InputStream} to read.
3444     * @param charset the charset to use, null means platform default.
3445     * @return the requested String.
3446     * @throws NullPointerException if the input is null.
3447     * @throws IOException          if an I/O error occurs.
3448     * @since 2.12.0
3449     */
3450    public static String toString(final IOSupplier<InputStream> input, final Charset charset) throws IOException {
3451        return toString(input, charset, () -> {
3452            throw new NullPointerException("input");
3453        });
3454    }
3455
3456    /**
3457     * Gets the contents of an {@link InputStream} from a supplier as a String
3458     * using the specified character encoding.
3459     * <p>
3460     * This method buffers the input internally, so there is no need to use a
3461     * {@link BufferedInputStream}.
3462     * </p>
3463     *
3464     * @param input supplies the {@link InputStream} to read.
3465     * @param charset the charset to use, null means platform default.
3466     * @param defaultString the default return value if the supplier or its value is null.
3467     * @return the requested String.
3468     * @throws NullPointerException if the input is null.
3469     * @throws IOException          if an I/O error occurs.
3470     * @since 2.12.0
3471     */
3472    public static String toString(final IOSupplier<InputStream> input, final Charset charset, final IOSupplier<String> defaultString) throws IOException {
3473        if (input == null) {
3474            return defaultString.get();
3475        }
3476        try (InputStream inputStream = input.get()) {
3477            return inputStream != null ? toString(inputStream, charset) : defaultString.get();
3478        }
3479    }
3480
3481    /**
3482     * Gets the contents of a {@link Reader} as a String.
3483     * <p>
3484     * This method buffers the input internally, so there is no need to use a
3485     * {@link BufferedReader}.
3486     * </p>
3487     *
3488     * @param reader the {@link Reader} to read.
3489     * @return the requested String.
3490     * @throws NullPointerException if the input is null.
3491     * @throws IOException          if an I/O error occurs.
3492     */
3493    public static String toString(final Reader reader) throws IOException {
3494        try (StringBuilderWriter sw = new StringBuilderWriter()) {
3495            copy(reader, sw);
3496            return sw.toString();
3497        }
3498    }
3499
3500    /**
3501     * Gets the contents at the given URI using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3502     *
3503     * @param uri The URI source.
3504     * @return The contents of the URL as a String.
3505     * @throws IOException if an I/O exception occurs.
3506     * @since 2.1
3507     * @deprecated Use {@link #toString(URI, Charset)} instead.
3508     */
3509    @Deprecated
3510    public static String toString(final URI uri) throws IOException {
3511        return toString(uri, Charset.defaultCharset());
3512    }
3513
3514    /**
3515     * Gets the contents at the given URI.
3516     *
3517     * @param uri The URI source.
3518     * @param encoding The encoding name for the URL contents.
3519     * @return The contents of the URL as a String.
3520     * @throws IOException if an I/O exception occurs.
3521     * @since 2.3.
3522     */
3523    public static String toString(final URI uri, final Charset encoding) throws IOException {
3524        return toString(uri.toURL(), Charsets.toCharset(encoding));
3525    }
3526
3527    /**
3528     * Gets the contents at the given URI.
3529     *
3530     * @param uri The URI source.
3531     * @param charsetName The encoding name for the URL contents.
3532     * @return The contents of the URL as a String.
3533     * @throws IOException                                  if an I/O exception occurs.
3534     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3535     * @since 2.1
3536     */
3537    public static String toString(final URI uri, final String charsetName) throws IOException {
3538        return toString(uri, Charsets.toCharset(charsetName));
3539    }
3540
3541    /**
3542     * Gets the contents at the given URL using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3543     *
3544     * @param url The URL source.
3545     * @return The contents of the URL as a String.
3546     * @throws IOException if an I/O exception occurs.
3547     * @since 2.1
3548     * @deprecated Use {@link #toString(URL, Charset)} instead.
3549     */
3550    @Deprecated
3551    public static String toString(final URL url) throws IOException {
3552        return toString(url, Charset.defaultCharset());
3553    }
3554
3555    /**
3556     * Gets the contents at the given URL.
3557     *
3558     * @param url The URL source.
3559     * @param encoding The encoding name for the URL contents.
3560     * @return The contents of the URL as a String.
3561     * @throws IOException if an I/O exception occurs.
3562     * @since 2.3
3563     */
3564    public static String toString(final URL url, final Charset encoding) throws IOException {
3565        return toString(url::openStream, encoding);
3566    }
3567
3568    /**
3569     * Gets the contents at the given URL.
3570     *
3571     * @param url The URL source.
3572     * @param charsetName The encoding name for the URL contents.
3573     * @return The contents of the URL as a String.
3574     * @throws IOException                                  if an I/O exception occurs.
3575     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3576     * @since 2.1
3577     */
3578    public static String toString(final URL url, final String charsetName) throws IOException {
3579        return toString(url, Charsets.toCharset(charsetName));
3580    }
3581
3582    /**
3583     * Writes bytes from a {@code byte[]} to an {@link OutputStream}.
3584     *
3585     * @param data   the byte array to write, do not modify during output, null ignored.
3586     * @param output the {@link OutputStream} to write to.
3587     * @throws NullPointerException if output is null.
3588     * @throws IOException          if an I/O error occurs.
3589     * @since 1.1
3590     */
3591    public static void write(final byte[] data, final OutputStream output)
3592            throws IOException {
3593        if (data != null) {
3594            output.write(data);
3595        }
3596    }
3597
3598    /**
3599     * Writes bytes from a {@code byte[]} to chars on a {@link Writer}
3600     * using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3601     * <p>
3602     * This method uses {@link String#String(byte[])}.
3603     * </p>
3604     *
3605     * @param data the byte array to write, do not modify during output,
3606     * null ignored
3607     * @param writer the {@link Writer} to write to.
3608     * @throws NullPointerException if output is null.
3609     * @throws IOException          if an I/O error occurs.
3610     * @since 1.1
3611     * @deprecated Use {@link #write(byte[], Writer, Charset)} instead.
3612     */
3613    @Deprecated
3614    public static void write(final byte[] data, final Writer writer) throws IOException {
3615        write(data, writer, Charset.defaultCharset());
3616    }
3617
3618    /**
3619     * Writes bytes from a {@code byte[]} to chars on a {@link Writer}
3620     * using the specified character encoding.
3621     * <p>
3622     * This method uses {@link String#String(byte[], String)}.
3623     * </p>
3624     *
3625     * @param data the byte array to write, do not modify during output,
3626     * null ignored
3627     * @param writer the {@link Writer} to write to.
3628     * @param charset the charset to use, null means platform default.
3629     * @throws NullPointerException if output is null.
3630     * @throws IOException          if an I/O error occurs.
3631     * @since 2.3
3632     */
3633    public static void write(final byte[] data, final Writer writer, final Charset charset) throws IOException {
3634        if (data != null) {
3635            writer.write(new String(data, Charsets.toCharset(charset)));
3636        }
3637    }
3638
3639    /**
3640     * Writes bytes from a {@code byte[]} to chars on a {@link Writer} using the specified character encoding.
3641     * <p>
3642     * Character encoding names can be found at <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3643     * </p>
3644     * <p>
3645     * This method uses {@link String#String(byte[], String)}.
3646     * </p>
3647     *
3648     * @param data        the byte array to write, do not modify during output, null ignored.
3649     * @param writer      the {@link Writer} to write to.
3650     * @param charsetName the name of the requested charset, null means platform default.
3651     * @throws NullPointerException                         if output is null.
3652     * @throws IOException                                  if an I/O error occurs.
3653     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3654     * @since 1.1
3655     */
3656    public static void write(final byte[] data, final Writer writer, final String charsetName) throws IOException {
3657        write(data, writer, Charsets.toCharset(charsetName));
3658    }
3659
3660    /**
3661     * Writes chars from a {@code char[]} to bytes on an {@link OutputStream}.
3662     * <p>
3663     * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3664     * </p>
3665     *
3666     * @param data   the char array to write, do not modify during output, null ignored.
3667     * @param output the {@link OutputStream} to write to.
3668     * @throws NullPointerException if output is null.
3669     * @throws IOException          if an I/O error occurs.
3670     * @since 1.1
3671     * @deprecated Use {@link #write(char[], OutputStream, Charset)} instead.
3672     */
3673    @Deprecated
3674    public static void write(final char[] data, final OutputStream output)
3675            throws IOException {
3676        write(data, output, Charset.defaultCharset());
3677    }
3678
3679    /**
3680     * Writes chars from a {@code char[]} to bytes on an {@link OutputStream} using the specified character encoding.
3681     * <p>
3682     * This method uses {@link String#String(char[])} and {@link String#getBytes(String)}.
3683     * </p>
3684     *
3685     * @param data    the char array to write, do not modify during output, null ignored.
3686     * @param output  the {@link OutputStream} to write to.
3687     * @param charset the charset to use, null means platform default.
3688     * @throws NullPointerException if output is null.
3689     * @throws IOException          if an I/O error occurs.
3690     * @since 2.3
3691     */
3692    public static void write(final char[] data, final OutputStream output, final Charset charset) throws IOException {
3693        if (data != null) {
3694            write(new String(data), output, charset);
3695        }
3696    }
3697
3698    /**
3699     * Writes chars from a {@code char[]} to bytes on an {@link OutputStream} using the specified character encoding.
3700     * <p>
3701     * Character encoding names can be found at <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3702     * </p>
3703     * <p>
3704     * This method uses {@link String#String(char[])} and {@link String#getBytes(String)}.
3705     * </p>
3706     *
3707     * @param data        the char array to write, do not modify during output, null ignored.
3708     * @param output      the {@link OutputStream} to write to.
3709     * @param charsetName the name of the requested charset, null means platform default.
3710     * @throws NullPointerException                         if output is null.
3711     * @throws IOException                                  if an I/O error occurs.
3712     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3713     * @since 1.1
3714     */
3715    public static void write(final char[] data, final OutputStream output, final String charsetName)
3716            throws IOException {
3717        write(data, output, Charsets.toCharset(charsetName));
3718    }
3719
3720    /**
3721     * Writes chars from a {@code char[]} to a {@link Writer}
3722     *
3723     * @param data   the char array to write, do not modify during output, null ignored.
3724     * @param writer the {@link Writer} to write to.
3725     * @throws NullPointerException if output is null.
3726     * @throws IOException          if an I/O error occurs.
3727     * @since 1.1
3728     */
3729    public static void write(final char[] data, final Writer writer) throws IOException {
3730        if (data != null) {
3731            writer.write(data);
3732        }
3733    }
3734
3735    /**
3736     * Writes chars from a {@link CharSequence} to bytes on an {@link OutputStream} using the virtual machine's {@link Charset#defaultCharset() default
3737     * charset}.
3738     * <p>
3739     * This method uses {@link String#getBytes()}.
3740     * </p>
3741     *
3742     * @param data   the {@link CharSequence} to write, null ignored.
3743     * @param output the {@link OutputStream} to write to.
3744     * @throws NullPointerException if output is null.
3745     * @throws IOException          if an I/O error occurs.
3746     * @since 2.0
3747     * @deprecated Use {@link #write(CharSequence, OutputStream, Charset)} instead.
3748     */
3749    @Deprecated
3750    public static void write(final CharSequence data, final OutputStream output)
3751            throws IOException {
3752        write(data, output, Charset.defaultCharset());
3753    }
3754
3755    /**
3756     * Writes chars from a {@link CharSequence} to bytes on an {@link OutputStream} using the specified character encoding.
3757     * <p>
3758     * This method uses {@link String#getBytes(String)}.
3759     * </p>
3760     *
3761     * @param data    the {@link CharSequence} to write, null ignored.
3762     * @param output  the {@link OutputStream} to write to.
3763     * @param charset the charset to use, null means platform default.
3764     * @throws NullPointerException if output is null.
3765     * @throws IOException          if an I/O error occurs.
3766     * @since 2.3
3767     */
3768    public static void write(final CharSequence data, final OutputStream output, final Charset charset)
3769            throws IOException {
3770        if (data != null) {
3771            write(data.toString(), output, charset);
3772        }
3773    }
3774
3775    /**
3776     * Writes chars from a {@link CharSequence} to bytes on an {@link OutputStream} using the specified character encoding.
3777     * <p>
3778     * Character encoding names can be found at <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3779     * </p>
3780     * <p>
3781     * This method uses {@link String#getBytes(String)}.
3782     * </p>
3783     *
3784     * @param data        the {@link CharSequence} to write, null ignored.
3785     * @param output      the {@link OutputStream} to write to.
3786     * @param charsetName the name of the requested charset, null means platform default.
3787     * @throws NullPointerException                         if output is null.
3788     * @throws IOException                                  if an I/O error occurs.
3789     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3790     * @since 2.0
3791     */
3792    public static void write(final CharSequence data, final OutputStream output, final String charsetName)
3793            throws IOException {
3794        write(data, output, Charsets.toCharset(charsetName));
3795    }
3796
3797    /**
3798     * Writes chars from a {@link CharSequence} to a {@link Writer}.
3799     *
3800     * @param data the {@link CharSequence} to write, null ignored.
3801     * @param writer the {@link Writer} to write to.
3802     * @throws NullPointerException if output is null.
3803     * @throws IOException          if an I/O error occurs.
3804     * @since 2.0
3805     */
3806    public static void write(final CharSequence data, final Writer writer) throws IOException {
3807        if (data != null) {
3808            write(data.toString(), writer);
3809        }
3810    }
3811
3812    /**
3813     * Writes chars from a {@link String} to bytes on an
3814     * {@link OutputStream} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
3815     * <p>
3816     * This method uses {@link String#getBytes()}.
3817     * </p>
3818     *
3819     * @param data the {@link String} to write, null ignored.
3820     * @param output the {@link OutputStream} to write to.
3821     * @throws NullPointerException if output is null.
3822     * @throws IOException          if an I/O error occurs.
3823     * @since 1.1
3824     * @deprecated Use {@link #write(String, OutputStream, Charset)} instead
3825     */
3826    @Deprecated
3827    public static void write(final String data, final OutputStream output)
3828            throws IOException {
3829        write(data, output, Charset.defaultCharset());
3830    }
3831
3832    /**
3833     * Writes chars from a {@link String} to bytes on an
3834     * {@link OutputStream} using the specified character encoding.
3835     * <p>
3836     * This method uses {@link String#getBytes(String)}.
3837     * </p>
3838     *
3839     * @param data the {@link String} to write, null ignored.
3840     * @param output the {@link OutputStream} to write to.
3841     * @param charset the charset to use, null means platform default.
3842     * @throws NullPointerException if output is null.
3843     * @throws IOException          if an I/O error occurs.
3844     * @since 2.3
3845     */
3846    @SuppressWarnings("resource")
3847    public static void write(final String data, final OutputStream output, final Charset charset) throws IOException {
3848        if (data != null) {
3849            // Use Charset#encode(String), since calling String#getBytes(Charset) might result in
3850            // NegativeArraySizeException or OutOfMemoryError.
3851            // The underlying OutputStream should not be closed, so the channel is not closed.
3852            Channels.newChannel(output).write(Charsets.toCharset(charset).encode(data));
3853        }
3854    }
3855
3856    /**
3857     * Writes chars from a {@link String} to bytes on an
3858     * {@link OutputStream} using the specified character encoding.
3859     * <p>
3860     * Character encoding names can be found at
3861     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3862     * </p>
3863     * <p>
3864     * This method uses {@link String#getBytes(String)}.
3865     * </p>
3866     *
3867     * @param data the {@link String} to write, null ignored.
3868     * @param output the {@link OutputStream} to write to.
3869     * @param charsetName the name of the requested charset, null means platform default.
3870     * @throws NullPointerException        if output is null.
3871     * @throws IOException                 if an I/O error occurs.
3872     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3873     * @since 1.1
3874     */
3875    public static void write(final String data, final OutputStream output, final String charsetName)
3876            throws IOException {
3877        write(data, output, Charsets.toCharset(charsetName));
3878    }
3879
3880    /**
3881     * Writes chars from a {@link String} to a {@link Writer}.
3882     *
3883     * @param data the {@link String} to write, null ignored.
3884     * @param writer the {@link Writer} to write to.
3885     * @throws NullPointerException if output is null.
3886     * @throws IOException          if an I/O error occurs.
3887     * @since 1.1
3888     */
3889    public static void write(final String data, final Writer writer) throws IOException {
3890        if (data != null) {
3891            writer.write(data);
3892        }
3893    }
3894
3895    /**
3896     * Writes chars from a {@link StringBuffer} to bytes on an
3897     * {@link OutputStream} using the default character encoding of the
3898     * platform.
3899     * <p>
3900     * This method uses {@link String#getBytes()}.
3901     * </p>
3902     *
3903     * @param data the {@link StringBuffer} to write, null ignored.
3904     * @param output the {@link OutputStream} to write to.
3905     * @throws NullPointerException if output is null.
3906     * @throws IOException          if an I/O error occurs
3907     * @since 1.1
3908     * @deprecated Use {@link #write(CharSequence, OutputStream)}.
3909     */
3910    @Deprecated
3911    public static void write(final StringBuffer data, final OutputStream output) //NOSONAR
3912            throws IOException {
3913        write(data, output, (String) null);
3914    }
3915
3916    /**
3917     * Writes chars from a {@link StringBuffer} to bytes on an
3918     * {@link OutputStream} using the specified character encoding.
3919     * <p>
3920     * Character encoding names can be found at
3921     * <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
3922     * </p>
3923     * <p>
3924     * This method uses {@link String#getBytes(String)}.
3925     * </p>
3926     *
3927     * @param data the {@link StringBuffer} to write, null ignored.
3928     * @param output the {@link OutputStream} to write to.
3929     * @param charsetName the name of the requested charset, null means platform default.
3930     * @throws NullPointerException        if output is null.
3931     * @throws IOException                 if an I/O error occurs.
3932     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
3933     * @since 1.1
3934     * @deprecated Use {@link #write(CharSequence, OutputStream, String)}.
3935     */
3936    @Deprecated
3937    public static void write(final StringBuffer data, final OutputStream output, final String charsetName) //NOSONAR
3938        throws IOException {
3939        if (data != null) {
3940            write(data.toString(), output, Charsets.toCharset(charsetName));
3941        }
3942    }
3943
3944    /**
3945     * Writes chars from a {@link StringBuffer} to a {@link Writer}.
3946     *
3947     * @param data the {@link StringBuffer} to write, null ignored.
3948     * @param writer the {@link Writer} to write to.
3949     * @throws NullPointerException if output is null.
3950     * @throws IOException          if an I/O error occurs.
3951     * @since 1.1
3952     * @deprecated Use {@link #write(CharSequence, Writer)}.
3953     */
3954    @Deprecated
3955    public static void write(final StringBuffer data, final Writer writer) //NOSONAR
3956            throws IOException {
3957        if (data != null) {
3958            writer.write(data.toString());
3959        }
3960    }
3961
3962    /**
3963     * Writes bytes from a {@code byte[]} to an {@link OutputStream} using chunked writes.
3964     * This is intended for writing very large byte arrays which might otherwise cause excessive
3965     * memory usage if the native code has to allocate a copy.
3966     *
3967     * @param data the byte array to write, do not modify during output,
3968     * null ignored.
3969     * @param output the {@link OutputStream} to write to.
3970     * @throws NullPointerException if output is null.
3971     * @throws IOException          if an I/O error occurs.
3972     * @since 2.5
3973     */
3974    public static void writeChunked(final byte[] data, final OutputStream output)
3975            throws IOException {
3976        if (data != null) {
3977            int bytes = data.length;
3978            int offset = 0;
3979            while (bytes > 0) {
3980                final int chunk = Math.min(bytes, DEFAULT_BUFFER_SIZE);
3981                output.write(data, offset, chunk);
3982                bytes -= chunk;
3983                offset += chunk;
3984            }
3985        }
3986    }
3987
3988    /**
3989     * Writes chars from a {@code char[]} to a {@link Writer} using chunked writes. This is intended for writing very large byte arrays which might otherwise
3990     * cause excessive memory usage if the native code has to allocate a copy.
3991     *
3992     * @param data   the char array to write, do not modify during output, null ignored.
3993     * @param writer the {@link Writer} to write to.
3994     * @throws NullPointerException if output is null.
3995     * @throws IOException          if an I/O error occurs.
3996     * @since 2.5
3997     */
3998    public static void writeChunked(final char[] data, final Writer writer) throws IOException {
3999        if (data != null) {
4000            int bytes = data.length;
4001            int offset = 0;
4002            while (bytes > 0) {
4003                final int chunk = Math.min(bytes, DEFAULT_BUFFER_SIZE);
4004                writer.write(data, offset, chunk);
4005                bytes -= chunk;
4006                offset += chunk;
4007            }
4008        }
4009    }
4010
4011    /**
4012     * Writes the {@link #toString()} value of each item in a collection to an {@link OutputStream} line by line, using the virtual machine's
4013     * {@linkplain Charset#defaultCharset() default charset} and the specified line ending.
4014     *
4015     * @param lines      the lines to write, null entries produce blank lines.
4016     * @param lineEnding the line separator to use, null is system default.
4017     * @param output     the {@link OutputStream} to write to, not null, not closed.
4018     * @throws NullPointerException if the output is null.
4019     * @throws IOException          if an I/O error occurs.
4020     * @since 1.1
4021     * @deprecated Use {@link #writeLines(Collection, String, OutputStream, Charset)} instead
4022     */
4023    @Deprecated
4024    public static void writeLines(final Collection<?> lines, final String lineEnding, final OutputStream output) throws IOException {
4025        writeLines(lines, lineEnding, output, Charset.defaultCharset());
4026    }
4027
4028    /**
4029     * Writes the {@link #toString()} value of each item in a collection to an {@link OutputStream} line by line, using the specified character encoding and the
4030     * specified line ending.
4031     * <p>
4032     * UTF-16 is written big-endian with no byte order mark. For little-endian, use UTF-16LE. For a BOM, write it to the stream before calling this method.
4033     * </p>
4034     *
4035     * @param lines      the lines to write, null entries produce blank lines.
4036     * @param lineEnding the line separator to use, null is system default.
4037     * @param output     the {@link OutputStream} to write to, not null, not closed.
4038     * @param charset    the charset to use, null means platform default.
4039     * @throws NullPointerException if output is null.
4040     * @throws IOException          if an I/O error occurs.
4041     * @since 2.3
4042     */
4043    public static void writeLines(final Collection<?> lines, String lineEnding, final OutputStream output, Charset charset) throws IOException {
4044        if (lines == null) {
4045            return;
4046        }
4047        if (lineEnding == null) {
4048            lineEnding = System.lineSeparator();
4049        }
4050        if (StandardCharsets.UTF_16.equals(charset)) {
4051            // don't write a BOM
4052            charset = StandardCharsets.UTF_16BE;
4053        }
4054        final byte[] eolBytes = lineEnding.getBytes(charset);
4055        for (final Object line : lines) {
4056            if (line != null) {
4057                write(line.toString(), output, charset);
4058            }
4059            output.write(eolBytes);
4060        }
4061    }
4062
4063    /**
4064     * Writes the {@link #toString()} value of each item in a collection to an {@link OutputStream} line by line, using the specified character encoding and the
4065     * specified line ending.
4066     * <p>
4067     * Character encoding names can be found at <a href="https://www.iana.org/assignments/character-sets">IANA</a>.
4068     * </p>
4069     *
4070     * @param lines       the lines to write, null entries produce blank lines.
4071     * @param lineEnding  the line separator to use, null is system default.
4072     * @param output      the {@link OutputStream} to write to, not null, not closed.
4073     * @param charsetName the name of the requested charset, null means platform default.
4074     * @throws NullPointerException                         if the output is null.
4075     * @throws IOException                                  if an I/O error occurs.
4076     * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
4077     * @since 1.1
4078     */
4079    public static void writeLines(final Collection<?> lines, final String lineEnding, final OutputStream output, final String charsetName) throws IOException {
4080        writeLines(lines, lineEnding, output, Charsets.toCharset(charsetName));
4081    }
4082
4083    /**
4084     * Writes the {@link #toString()} value of each item in a collection to a {@link Writer} line by line, using the specified line ending.
4085     *
4086     * @param lines      the lines to write, null entries produce blank lines.
4087     * @param lineEnding the line separator to use, null is system default.
4088     * @param writer     the {@link Writer} to write to, not null, not closed.
4089     * @throws NullPointerException if the input is null.
4090     * @throws IOException          if an I/O error occurs.
4091     * @since 1.1
4092     */
4093    public static void writeLines(final Collection<?> lines, String lineEnding, final Writer writer) throws IOException {
4094        if (lines == null) {
4095            return;
4096        }
4097        if (lineEnding == null) {
4098            lineEnding = System.lineSeparator();
4099        }
4100        for (final Object line : lines) {
4101            if (line != null) {
4102                writer.write(line.toString());
4103            }
4104            writer.write(lineEnding);
4105        }
4106    }
4107
4108    /**
4109     * Returns the given Appendable if it is already a {@link Writer}, otherwise creates a Writer wrapper around the
4110     * given Appendable.
4111     *
4112     * @param appendable the Appendable to wrap or return (not null).
4113     * @return  the given Appendable or a Writer wrapper around the given Appendable.
4114     * @throws NullPointerException if the input parameter is null.
4115     * @since 2.7
4116     */
4117    public static Writer writer(final Appendable appendable) {
4118        Objects.requireNonNull(appendable, "appendable");
4119        if (appendable instanceof Writer) {
4120            return (Writer) appendable;
4121        }
4122        if (appendable instanceof StringBuilder) {
4123            return new StringBuilderWriter((StringBuilder) appendable);
4124        }
4125        return new AppendableWriter<>(appendable);
4126    }
4127
4128    /**
4129     * Instances should NOT be constructed in standard programming.
4130     *
4131     * @deprecated TODO Make private in 3.0.
4132     */
4133    @Deprecated
4134    public IOUtils() { //NOSONAR
4135        // empty
4136    }
4137
4138}