    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 * http://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019package org.apache.commons.compress.utils;
    020
    021import java.io.ByteArrayOutputStream;
    022import java.io.Closeable;
    023import java.io.EOFException;
    024import java.io.File;
    025import java.io.IOException;
    026import java.io.InputStream;
    027import java.io.OutputStream;
    028import java.nio.ByteBuffer;
    029import java.nio.channels.ReadableByteChannel;
    030import java.nio.file.Files;
    031import java.nio.file.LinkOption;
    032
    033import org.apache.commons.io.FileUtils;
    034
    035/**
    036 * Utility functions.
    037 *
    038 * @Immutable (has mutable data but it is write-only).
    039 */
    040public final class IOUtils {
    041
    042    private static final int COPY_BUF_SIZE = 8024;
    043
    044    /**
    045     * Empty array of type {@link LinkOption}.
    046     *
    047     * @since 1.21
    048     */
    049    public static final LinkOption[] EMPTY_LINK_OPTIONS = {};
    050
    051    /**
    052     * Closes the given Closeable and swallows any IOException that may occur.
    053     *
    054     * @param c Closeable to close, can be null
    055     * @since 1.7
    056     * @deprecated Use {@link org.apache.commons.io.IOUtils#closeQuietly(Closeable)}.
    057     */
    058    @Deprecated
    059    public static void closeQuietly(final Closeable c) {
    060        org.apache.commons.io.IOUtils.closeQuietly(c);
    061    }
    062
    063    /**
    064     * Copies the source file to the given output stream.
    065     *
    066     * @param sourceFile   The file to read.
    067     * @param outputStream The output stream to write.
    068     * @throws IOException if an I/O error occurs when reading or writing.
    069     * @since 1.21
    070     * @deprecated Use {@link FileUtils#copyFile(File, OutputStream)}.
    071     */
    072    @Deprecated
    073    public static void copy(final File sourceFile, final OutputStream outputStream) throws IOException {
    074        FileUtils.copyFile(sourceFile, outputStream);
    075    }
    076
    077    /**
    078     * Copies the content of a InputStream into an OutputStream. Uses a default buffer size of 8024 bytes.
    079     *
    080     * @param input  the InputStream to copy
    081     * @param output the target, may be null to simulate output to dev/null on Linux and NUL on Windows
    082     * @return the number of bytes copied
    083     * @throws IOException if an error occurs
    084     * @deprecated Use {@link org.apache.commons.io.IOUtils#copy(InputStream, OutputStream)}.
    085     */
    086    @Deprecated
    087    public static long copy(final InputStream input, final OutputStream output) throws IOException {
    088        return org.apache.commons.io.IOUtils.copy(input, output);
    089    }
    090
    091    /**
    092     * Copies the content of a InputStream into an OutputStream
    093     *
    094     * @param input      the InputStream to copy
    095     * @param output     the target, may be null to simulate output to dev/null on Linux and NUL on Windows
    096     * @param bufferSize the buffer size to use, must be bigger than 0
    097     * @return the number of bytes copied
    098     * @throws IOException              if an error occurs
    099     * @throws IllegalArgumentException if bufferSize is smaller than or equal to 0
    100     * @deprecated Use {@link org.apache.commons.io.IOUtils#copy(InputStream, OutputStream, int)}.
    101     */
    102    @Deprecated
    103    public static long copy(final InputStream input, final OutputStream output, final int bufferSize) throws IOException {
    104        return org.apache.commons.io.IOUtils.copy(input, output, bufferSize);
    105    }
    106
    107    /**
    108     * Copies part of the content of a InputStream into an OutputStream. Uses a default buffer size of 8024 bytes.
    109     *
    110     * @param input  the InputStream to copy
    111     * @param output the target Stream
    112     * @param len    maximum amount of bytes to copy
    113     * @return the number of bytes copied
    114     * @throws IOException if an error occurs
    115     * @since 1.21
    116     * @deprecated Use {@link org.apache.commons.io.IOUtils#copyLarge(InputStream, OutputStream, long, long)}.
    117     */
    118    @Deprecated
    119    public static long copyRange(final InputStream input, final long len, final OutputStream output) throws IOException {
    120        return org.apache.commons.io.IOUtils.copyLarge(input, output, 0, len);
    121    }
    122
    123    /**
    124     * Copies part of the content of a InputStream into an OutputStream
    125     *
    126     * @param input      the InputStream to copy
    127     * @param length        maximum amount of bytes to copy
    128     * @param output     the target, may be null to simulate output to dev/null on Linux and NUL on Windows
    129     * @param bufferSize the buffer size to use, must be bigger than 0
    130     * @return the number of bytes copied
    131     * @throws IOException              if an error occurs
    132     * @throws IllegalArgumentException if bufferSize is smaller than or equal to 0
    133     * @since 1.21
    134     * @deprecated No longer used.
    135     */
    136    @Deprecated
    137    public static long copyRange(final InputStream input, final long length, final OutputStream output, final int bufferSize) throws IOException {
    138        if (bufferSize < 1) {
    139            throw new IllegalArgumentException("bufferSize must be bigger than 0");
    140        }
    141        final byte[] buffer = new byte[(int) Math.min(bufferSize, Math.max(0, length))];
    142        int n = 0;
    143        long count = 0;
    144        while (count < length && -1 != (n = input.read(buffer, 0, (int) Math.min(length - count, buffer.length)))) {
    145            if (output != null) {
    146                output.write(buffer, 0, n);
    147            }
    148            count += n;
    149        }
    150        return count;
    151    }
    152
    153    /**
    154     * Reads as much from the file as possible to fill the given array.
    155     * <p>
    156     * This method may invoke read repeatedly to fill the array and only read less bytes than the length of the array if the end of the stream has been reached.
    157     * </p>
    158     *
    159     * @param file  file to read
    160     * @param array buffer to fill
    161     * @return the number of bytes actually read
    162     * @throws IOException on error
    163     * @since 1.20
    164     * @deprecated Use {@link Files#readAllBytes(java.nio.file.Path)}.
    165     */
    166    @Deprecated
    167    public static int read(final File file, final byte[] array) throws IOException {
    168        try (InputStream inputStream = Files.newInputStream(file.toPath())) {
    169            return readFully(inputStream, array, 0, array.length);
    170        }
    171    }
    172
    173    /**
    174     * Reads as much from input as possible to fill the given array.
    175     * <p>
    176     * This method may invoke read repeatedly to fill the array and only read less bytes than the length of the array if the end of the stream has been reached.
    177     * </p>
    178     *
    179     * @param input stream to read from
    180     * @param array buffer to fill
    181     * @return the number of bytes actually read
    182     * @throws IOException on error
    183     */
    184    public static int readFully(final InputStream input, final byte[] array) throws IOException {
    185        return readFully(input, array, 0, array.length);
    186    }
    187
    188    /**
    189     * Reads as much from input as possible to fill the given array with the given amount of bytes.
    190     * <p>
    191     * This method may invoke read repeatedly to read the bytes and only read less bytes than the requested length if the end of the stream has been reached.
    192     * </p>
    193     *
    194     * @param input  stream to read from
    195     * @param array  buffer to fill
    196     * @param offset offset into the buffer to start filling at
    197     * @param length    of bytes to read
    198     * @return the number of bytes actually read
    199     * @throws IOException if an I/O error has occurred
    200     */
    201    public static int readFully(final InputStream input, final byte[] array, final int offset, final int length) throws IOException {
    202        if (length < 0 || offset < 0 || length + offset > array.length || length + offset < 0) {
    203            throw new IndexOutOfBoundsException();
    204        }
    205        return org.apache.commons.io.IOUtils.read(input, array, offset, length);
    206    }
    207
    208    /**
    209     * Reads {@code b.remaining()} bytes from the given channel starting at the current channel's position.
    210     * <p>
    211     * This method reads repeatedly from the channel until the requested number of bytes are read. This method blocks until the requested number of bytes are
    212     * read, the end of the channel is detected, or an exception is thrown.
    213     * </p>
    214     *
    215     * @param channel    the channel to read from
    216     * @param byteBuffer the buffer into which the data is read.
    217     * @throws IOException  if an I/O error occurs.
    218     * @throws EOFException if the channel reaches the end before reading all the bytes.
    219     */
    220    public static void readFully(final ReadableByteChannel channel, final ByteBuffer byteBuffer) throws IOException {
    221        final int expectedLength = byteBuffer.remaining();
    222        final int read = org.apache.commons.io.IOUtils.read(channel, byteBuffer);
    223        if (read < expectedLength) {
    224            throw new EOFException();
    225        }
    226    }
    227
    228    /**
    229     * Gets part of the contents of an {@code InputStream} as a {@code byte[]}.
    230     *
    231     * @param input the {@code InputStream} to read from
    232     * @param length   maximum amount of bytes to copy
    233     * @return the requested byte array
    234     * @throws NullPointerException if the input is null
    235     * @throws IOException          if an I/O error occurs
    236     * @since 1.21
    237     */
    238    public static byte[] readRange(final InputStream input, final int length) throws IOException {
    239        final ByteArrayOutputStream output = new ByteArrayOutputStream();
    240        org.apache.commons.io.IOUtils.copyLarge(input, output, 0, length);
    241        return output.toByteArray();
    242    }
    243
    244    /**
    245     * Gets part of the contents of an {@code ReadableByteChannel} as a {@code byte[]}.
    246     *
    247     * @param input the {@code ReadableByteChannel} to read from
    248     * @param length   maximum amount of bytes to copy
    249     * @return the requested byte array
    250     * @throws NullPointerException if the input is null
    251     * @throws IOException          if an I/O error occurs
    252     * @since 1.21
    253     */
    254    public static byte[] readRange(final ReadableByteChannel input, final int length) throws IOException {
    255        final ByteArrayOutputStream output = new ByteArrayOutputStream();
    256        final ByteBuffer b = ByteBuffer.allocate(Math.min(length, COPY_BUF_SIZE));
    257        int read = 0;
    258        while (read < length) {
    259            // Make sure we never read more than len bytes
    260            b.limit(Math.min(length - read, b.capacity()));
    261            final int readNow = input.read(b);
    262            if (readNow <= 0) {
    263                break;
    264            }
    265            output.write(b.array(), 0, readNow);
    266            b.rewind();
    267            read += readNow;
    268        }
    269        return output.toByteArray();
    270    }
    271
    272    /**
    273     * Skips the given number of bytes by repeatedly invoking skip on the given input stream if necessary.
    274     * <p>
    275     * In a case where the stream's skip() method returns 0 before the requested number of bytes has been skip this implementation will fall back to using the
    276     * read() method.
    277     * </p>
    278     * <p>
    279     * This method will only skip less than the requested number of bytes if the end of the input stream has been reached.
    280     * </p>
    281     *
    282     * @param input     stream to skip bytes in
    283     * @param numToSkip the number of bytes to skip
    284     * @return the number of bytes actually skipped
    285     * @throws IOException on error
    286     * @deprecated Use {@link org.apache.commons.io.IOUtils#skip(InputStream, long)}.
    287     */
    288    @Deprecated
    289    public static long skip(final InputStream input, final long numToSkip) throws IOException {
    290        return org.apache.commons.io.IOUtils.skip(input, numToSkip);
    291    }
    292
    293    /**
    294     * Gets the contents of an {@code InputStream} as a {@code byte[]}.
    295     * <p>
    296     * This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}.
    297     * </p>
    298     *
    299     * @param input the {@code InputStream} to read from
    300     * @return the requested byte array
    301     * @throws NullPointerException if the input is null
    302     * @throws IOException          if an I/O error occurs
    303     * @since 1.5
    304     * @deprecated Use {@link org.apache.commons.io.IOUtils#toByteArray(InputStream)}.
    305     */
    306    @Deprecated
    307    public static byte[] toByteArray(final InputStream input) throws IOException {
    308        return org.apache.commons.io.IOUtils.toByteArray(input);
    309    }
    310
    311    /** Private constructor to prevent instantiation of this utility class. */
    312    private IOUtils() {
    313    }
    314
    315}