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 }