1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
|
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tomcat.util.http.fileupload;
import java.io.Closeable;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* General IO stream manipulation utilities.
* <p>
* This class provides static utility methods for input/output operations.
* <ul>
* <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
* <li>toXxx/read - these methods read data from a stream
* <li>write - these methods write data to a stream
* <li>copy - these methods copy all the data from one stream to another
* <li>contentEquals - these methods compare the content of two streams
* </ul>
* <p>
* The byte-to-char methods and char-to-byte methods involve a conversion step.
* Two methods are provided in each case, one that uses the platform default
* encoding and the other which allows you to specify an encoding. You are
* encouraged to always specify an encoding because relying on the platform
* default can lead to unexpected results, for example when moving from
* development to production.
* <p>
* All the methods in this class that read a stream are buffered internally.
* This means that there is no cause to use a <code>BufferedInputStream</code>
* or <code>BufferedReader</code>. The default buffer size of 4K has been shown
* to be efficient in tests.
* <p>
* Wherever possible, the methods in this class do <em>not</em> flush or close
* the stream. This is to avoid making non-portable assumptions about the
* streams' origin and further use. Thus the caller is still responsible for
* closing streams after use.
* <p>
* Origin of code: Excalibur.
*/
public class IOUtils {
// NOTE: This class is focussed on InputStream, OutputStream, Reader and
// Writer. Each method should take at least one of these as a parameter,
// or return one of them.
private static final int EOF = -1;
/**
* The default buffer size ({@value}) to use for
* {@link #copyLarge(InputStream, OutputStream)}
* and
* {@link #copyLarge(Reader, Writer)}
*/
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
/**
* Instances should NOT be constructed in standard programming.
*/
public IOUtils() {
super();
}
/**
* Closes a <code>Closeable</code> unconditionally.
* <p>
* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in
* finally blocks.
* <p>
* Example code:
*
* <pre>
* Closeable closeable = null;
* try {
* closeable = new FileReader("foo.txt");
* // process closeable
* closeable.close();
* } catch (Exception e) {
* // error handling
* } finally {
* IOUtils.closeQuietly(closeable);
* }
* </pre>
*
* Closing all streams:
*
* <pre>
* try {
* return IOUtils.copy(inputStream, outputStream);
* } finally {
* IOUtils.closeQuietly(inputStream);
* IOUtils.closeQuietly(outputStream);
* }
* </pre>
*
* @param closeable
* the objects to close, may be null or already closed
* @since 2.0
*/
public static void closeQuietly(final Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (final IOException ioe) {
// ignore
}
}
// copy from InputStream
//-----------------------------------------------------------------------
/**
* Copy bytes from an <code>InputStream</code> to an
* <code>OutputStream</code>.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.
* <p>
* Large streams (over 2GB) will return a bytes copied value of
* <code>-1</code> after the copy has completed since the correct
* number of bytes cannot be returned as an int. For large streams
* use the <code>copyLarge(InputStream, OutputStream)</code> method.
*
* @param input the <code>InputStream</code> to read from
* @param output the <code>OutputStream</code> to write to
* @return the number of bytes copied, or -1 if > Integer.MAX_VALUE
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 1.1
*/
public static int copy(InputStream input, OutputStream output) throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
/**
* Copy bytes from a large (over 2GB) <code>InputStream</code> to an
* <code>OutputStream</code>.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.
* <p>
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
* @param input the <code>InputStream</code> to read from
* @param output the <code>OutputStream</code> to write to
* @return the number of bytes copied
* @throws NullPointerException if the input or output is null
* @throws IOException if an I/O error occurs
* @since 1.3
*/
public static long copyLarge(InputStream input, OutputStream output)
throws IOException {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
/**
* Reads bytes from an input stream.
* This implementation guarantees that it will read as many bytes
* as possible before giving up; this may not always be the case for
* subclasses of {@link InputStream}.
*
* @param input where to read input from
* @param buffer destination
* @param offset initial offset into buffer
* @param length length to read, must be >= 0
* @return actual length read; may be less than requested if EOF was reached
* @throws IOException if a read error occurs
* @since 2.2
*/
public static int read(final InputStream input, final byte[] buffer, final int offset, final int length) throws IOException {
if (length < 0) {
throw new IllegalArgumentException("Length must not be negative: " + length);
}
int remaining = length;
while (remaining > 0) {
final int location = length - remaining;
final int count = input.read(buffer, offset + location, remaining);
if (EOF == count) { // EOF
break;
}
remaining -= count;
}
return length - remaining;
}
/**
* Reads the requested number of bytes or fail if there are not enough left.
* <p>
* This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
* not read as many bytes as requested (most likely because of reaching EOF).
*
* @param input where to read input from
* @param buffer destination
* @param offset initial offset into buffer
* @param length length to read, must be >= 0
*
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if length is negative
* @throws EOFException if the number of bytes read was incorrect
* @since 2.2
*/
public static void readFully(final InputStream input, final byte[] buffer, final int offset, final int length) throws IOException {
final int actual = read(input, buffer, offset, length);
if (actual != length) {
throw new EOFException("Length to read: " + length + " actual: " + actual);
}
}
/**
* Reads the requested number of bytes or fail if there are not enough left.
* <p>
* This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
* not read as many bytes as requested (most likely because of reaching EOF).
*
* @param input where to read input from
* @param buffer destination
*
* @throws IOException if there is a problem reading the file
* @throws IllegalArgumentException if length is negative
* @throws EOFException if the number of bytes read was incorrect
* @since 2.2
*/
public static void readFully(final InputStream input, final byte[] buffer) throws IOException {
readFully(input, buffer, 0, buffer.length);
}
}
|