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, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.hadoop.io;
020
021 import java.io.*;
022 import java.net.Socket;
023
024 import org.apache.commons.logging.Log;
025
026 import org.apache.hadoop.classification.InterfaceAudience;
027 import org.apache.hadoop.classification.InterfaceStability;
028 import org.apache.hadoop.conf.Configuration;
029
030 /**
031 * An utility class for I/O related functionality.
032 */
033 @InterfaceAudience.Public
034 @InterfaceStability.Evolving
035 public class IOUtils {
036
037 /**
038 * Copies from one stream to another.
039 *
040 * @param in InputStrem to read from
041 * @param out OutputStream to write to
042 * @param buffSize the size of the buffer
043 * @param close whether or not close the InputStream and
044 * OutputStream at the end. The streams are closed in the finally clause.
045 */
046 public static void copyBytes(InputStream in, OutputStream out, int buffSize, boolean close)
047 throws IOException {
048 try {
049 copyBytes(in, out, buffSize);
050 if(close) {
051 out.close();
052 out = null;
053 in.close();
054 in = null;
055 }
056 } finally {
057 if(close) {
058 closeStream(out);
059 closeStream(in);
060 }
061 }
062 }
063
064 /**
065 * Copies from one stream to another.
066 *
067 * @param in InputStrem to read from
068 * @param out OutputStream to write to
069 * @param buffSize the size of the buffer
070 */
071 public static void copyBytes(InputStream in, OutputStream out, int buffSize)
072 throws IOException {
073 PrintStream ps = out instanceof PrintStream ? (PrintStream)out : null;
074 byte buf[] = new byte[buffSize];
075 int bytesRead = in.read(buf);
076 while (bytesRead >= 0) {
077 out.write(buf, 0, bytesRead);
078 if ((ps != null) && ps.checkError()) {
079 throw new IOException("Unable to write to output stream.");
080 }
081 bytesRead = in.read(buf);
082 }
083 }
084
085 /**
086 * Copies from one stream to another. <strong>closes the input and output streams
087 * at the end</strong>.
088 *
089 * @param in InputStrem to read from
090 * @param out OutputStream to write to
091 * @param conf the Configuration object
092 */
093 public static void copyBytes(InputStream in, OutputStream out, Configuration conf)
094 throws IOException {
095 copyBytes(in, out, conf.getInt("io.file.buffer.size", 4096), true);
096 }
097
098 /**
099 * Copies from one stream to another.
100 *
101 * @param in InputStream to read from
102 * @param out OutputStream to write to
103 * @param conf the Configuration object
104 * @param close whether or not close the InputStream and
105 * OutputStream at the end. The streams are closed in the finally clause.
106 */
107 public static void copyBytes(InputStream in, OutputStream out, Configuration conf, boolean close)
108 throws IOException {
109 copyBytes(in, out, conf.getInt("io.file.buffer.size", 4096), close);
110 }
111
112 /**
113 * Copies count bytes from one stream to another.
114 *
115 * @param in InputStream to read from
116 * @param out OutputStream to write to
117 * @param count number of bytes to copy
118 * @param close whether to close the streams
119 * @throws IOException if bytes can not be read or written
120 */
121 public static void copyBytes(InputStream in, OutputStream out, long count,
122 boolean close) throws IOException {
123 byte buf[] = new byte[4096];
124 long bytesRemaining = count;
125 int bytesRead;
126
127 try {
128 while (bytesRemaining > 0) {
129 int bytesToRead = (int)
130 (bytesRemaining < buf.length ? bytesRemaining : buf.length);
131
132 bytesRead = in.read(buf, 0, bytesToRead);
133 if (bytesRead == -1)
134 break;
135
136 out.write(buf, 0, bytesRead);
137 bytesRemaining -= bytesRead;
138 }
139 if (close) {
140 out.close();
141 out = null;
142 in.close();
143 in = null;
144 }
145 } finally {
146 if (close) {
147 closeStream(out);
148 closeStream(in);
149 }
150 }
151 }
152
153 /**
154 * Reads len bytes in a loop.
155 *
156 * @param in InputStream to read from
157 * @param buf The buffer to fill
158 * @param off offset from the buffer
159 * @param len the length of bytes to read
160 * @throws IOException if it could not read requested number of bytes
161 * for any reason (including EOF)
162 */
163 public static void readFully(InputStream in, byte buf[],
164 int off, int len) throws IOException {
165 int toRead = len;
166 while (toRead > 0) {
167 int ret = in.read(buf, off, toRead);
168 if (ret < 0) {
169 throw new IOException( "Premature EOF from inputStream");
170 }
171 toRead -= ret;
172 off += ret;
173 }
174 }
175
176 /**
177 * Similar to readFully(). Skips bytes in a loop.
178 * @param in The InputStream to skip bytes from
179 * @param len number of bytes to skip.
180 * @throws IOException if it could not skip requested number of bytes
181 * for any reason (including EOF)
182 */
183 public static void skipFully(InputStream in, long len) throws IOException {
184 while (len > 0) {
185 long ret = in.skip(len);
186 if (ret < 0) {
187 throw new IOException( "Premature EOF from inputStream");
188 }
189 len -= ret;
190 }
191 }
192
193 /**
194 * Close the Closeable objects and <b>ignore</b> any {@link IOException} or
195 * null pointers. Must only be used for cleanup in exception handlers.
196 *
197 * @param log the log to record problems to at debug level. Can be null.
198 * @param closeables the objects to close
199 */
200 public static void cleanup(Log log, java.io.Closeable... closeables) {
201 for (java.io.Closeable c : closeables) {
202 if (c != null) {
203 try {
204 c.close();
205 } catch(IOException e) {
206 if (log != null && log.isDebugEnabled()) {
207 log.debug("Exception in closing " + c, e);
208 }
209 }
210 }
211 }
212 }
213
214 /**
215 * Closes the stream ignoring {@link IOException}.
216 * Must only be called in cleaning up from exception handlers.
217 *
218 * @param stream the Stream to close
219 */
220 public static void closeStream(java.io.Closeable stream) {
221 cleanup(null, stream);
222 }
223
224 /**
225 * Closes the socket ignoring {@link IOException}
226 *
227 * @param sock the Socket to close
228 */
229 public static void closeSocket(Socket sock) {
230 if (sock != null) {
231 try {
232 sock.close();
233 } catch (IOException ignored) {
234 }
235 }
236 }
237
238 /**
239 * The /dev/null of OutputStreams.
240 */
241 public static class NullOutputStream extends OutputStream {
242 public void write(byte[] b, int off, int len) throws IOException {
243 }
244
245 public void write(int b) throws IOException {
246 }
247 }
248 }