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 * http://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 018 package org.apache.commons.net.io; 019 020 import java.io.IOException; 021 import java.io.InputStream; 022 import java.io.OutputStream; 023 import java.io.Reader; 024 import java.io.Writer; 025 026 /*** 027 * The Util class cannot be instantiated and stores short static convenience 028 * methods that are often quite useful. 029 * <p> 030 * <p> 031 * @see CopyStreamException 032 * @see CopyStreamListener 033 * @see CopyStreamAdapter 034 * @author Daniel F. Savarese 035 ***/ 036 037 public final class Util 038 { 039 /*** 040 * The default buffer size used by {@link #copyStream copyStream } 041 * and {@link #copyReader copyReader }. It's value is 1024. 042 ***/ 043 public static final int DEFAULT_COPY_BUFFER_SIZE = 1024; 044 045 // Cannot be instantiated 046 private Util() 047 { } 048 049 050 /*** 051 * Copies the contents of an InputStream to an OutputStream using a 052 * copy buffer of a given size and notifies the provided 053 * CopyStreamListener of the progress of the copy operation by calling 054 * its bytesTransferred(long, int) method after each write to the 055 * destination. If you wish to notify more than one listener you should 056 * use a CopyStreamAdapter as the listener and register the additional 057 * listeners with the CopyStreamAdapter. 058 * <p> 059 * The contents of the InputStream are 060 * read until the end of the stream is reached, but neither the 061 * source nor the destination are closed. You must do this yourself 062 * outside of the method call. The number of bytes read/written is 063 * returned. 064 * <p> 065 * @param source The source InputStream. 066 * @param dest The destination OutputStream. 067 * @param bufferSize The number of bytes to buffer during the copy. 068 * @param streamSize The number of bytes in the stream being copied. 069 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown. 070 * @param listener The CopyStreamListener to notify of progress. If 071 * this parameter is null, notification is not attempted. 072 * @param flush Whether to flush the output stream after every 073 * write. This is necessary for interactive sessions that rely on 074 * buffered streams. If you don't flush, the data will stay in 075 * the stream buffer. 076 * @exception CopyStreamException If an error occurs while reading from the 077 * source or writing to the destination. The CopyStreamException 078 * will contain the number of bytes confirmed to have been 079 * transferred before an 080 * IOException occurred, and it will also contain the IOException 081 * that caused the error. These values can be retrieved with 082 * the CopyStreamException getTotalBytesTransferred() and 083 * getIOException() methods. 084 ***/ 085 public static final long copyStream(InputStream source, OutputStream dest, 086 int bufferSize, long streamSize, 087 CopyStreamListener listener, 088 boolean flush) 089 throws CopyStreamException 090 { 091 int bytes; 092 long total; 093 byte[] buffer; 094 095 buffer = new byte[bufferSize]; 096 total = 0; 097 098 try 099 { 100 while ((bytes = source.read(buffer)) != -1) 101 { 102 // Technically, some read(byte[]) methods may return 0 and we cannot 103 // accept that as an indication of EOF. 104 105 if (bytes == 0) 106 { 107 bytes = source.read(); 108 if (bytes < 0) 109 break; 110 dest.write(bytes); 111 if(flush) 112 dest.flush(); 113 ++total; 114 if (listener != null) 115 listener.bytesTransferred(total, 1, streamSize); 116 continue; 117 } 118 119 dest.write(buffer, 0, bytes); 120 if(flush) 121 dest.flush(); 122 total += bytes; 123 if (listener != null) 124 listener.bytesTransferred(total, bytes, streamSize); 125 } 126 } 127 catch (IOException e) 128 { 129 throw new CopyStreamException("IOException caught while copying.", 130 total, e); 131 } 132 133 return total; 134 } 135 136 137 /*** 138 * Copies the contents of an InputStream to an OutputStream using a 139 * copy buffer of a given size and notifies the provided 140 * CopyStreamListener of the progress of the copy operation by calling 141 * its bytesTransferred(long, int) method after each write to the 142 * destination. If you wish to notify more than one listener you should 143 * use a CopyStreamAdapter as the listener and register the additional 144 * listeners with the CopyStreamAdapter. 145 * <p> 146 * The contents of the InputStream are 147 * read until the end of the stream is reached, but neither the 148 * source nor the destination are closed. You must do this yourself 149 * outside of the method call. The number of bytes read/written is 150 * returned. 151 * <p> 152 * @param source The source InputStream. 153 * @param dest The destination OutputStream. 154 * @param bufferSize The number of bytes to buffer during the copy. 155 * @param streamSize The number of bytes in the stream being copied. 156 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown. 157 * @param listener The CopyStreamListener to notify of progress. If 158 * this parameter is null, notification is not attempted. 159 * @exception CopyStreamException If an error occurs while reading from the 160 * source or writing to the destination. The CopyStreamException 161 * will contain the number of bytes confirmed to have been 162 * transferred before an 163 * IOException occurred, and it will also contain the IOException 164 * that caused the error. These values can be retrieved with 165 * the CopyStreamException getTotalBytesTransferred() and 166 * getIOException() methods. 167 ***/ 168 public static final long copyStream(InputStream source, OutputStream dest, 169 int bufferSize, long streamSize, 170 CopyStreamListener listener) 171 throws CopyStreamException 172 { 173 return copyStream(source, dest, bufferSize, streamSize, listener, 174 true); 175 } 176 177 178 /*** 179 * Copies the contents of an InputStream to an OutputStream using a 180 * copy buffer of a given size. The contents of the InputStream are 181 * read until the end of the stream is reached, but neither the 182 * source nor the destination are closed. You must do this yourself 183 * outside of the method call. The number of bytes read/written is 184 * returned. 185 * <p> 186 * @param source The source InputStream. 187 * @param dest The destination OutputStream. 188 * @return The number of bytes read/written in the copy operation. 189 * @exception CopyStreamException If an error occurs while reading from the 190 * source or writing to the destination. The CopyStreamException 191 * will contain the number of bytes confirmed to have been 192 * transferred before an 193 * IOException occurred, and it will also contain the IOException 194 * that caused the error. These values can be retrieved with 195 * the CopyStreamException getTotalBytesTransferred() and 196 * getIOException() methods. 197 ***/ 198 public static final long copyStream(InputStream source, OutputStream dest, 199 int bufferSize) 200 throws CopyStreamException 201 { 202 return copyStream(source, dest, bufferSize, 203 CopyStreamEvent.UNKNOWN_STREAM_SIZE, null); 204 } 205 206 207 /*** 208 * Same as <code> copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code> 209 ***/ 210 public static final long copyStream(InputStream source, OutputStream dest) 211 throws CopyStreamException 212 { 213 return copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE); 214 } 215 216 217 /*** 218 * Copies the contents of a Reader to a Writer using a 219 * copy buffer of a given size and notifies the provided 220 * CopyStreamListener of the progress of the copy operation by calling 221 * its bytesTransferred(long, int) method after each write to the 222 * destination. If you wish to notify more than one listener you should 223 * use a CopyStreamAdapter as the listener and register the additional 224 * listeners with the CopyStreamAdapter. 225 * <p> 226 * The contents of the Reader are 227 * read until its end is reached, but neither the source nor the 228 * destination are closed. You must do this yourself outside of the 229 * method call. The number of characters read/written is returned. 230 * <p> 231 * @param source The source Reader. 232 * @param dest The destination writer. 233 * @param bufferSize The number of characters to buffer during the copy. 234 * @param streamSize The number of characters in the stream being copied. 235 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown. 236 * @param listener The CopyStreamListener to notify of progress. If 237 * this parameter is null, notification is not attempted. 238 * @return The number of characters read/written in the copy operation. 239 * @exception CopyStreamException If an error occurs while reading from the 240 * source or writing to the destination. The CopyStreamException 241 * will contain the number of bytes confirmed to have been 242 * transferred before an 243 * IOException occurred, and it will also contain the IOException 244 * that caused the error. These values can be retrieved with 245 * the CopyStreamException getTotalBytesTransferred() and 246 * getIOException() methods. 247 ***/ 248 public static final long copyReader(Reader source, Writer dest, 249 int bufferSize, long streamSize, 250 CopyStreamListener listener) 251 throws CopyStreamException 252 { 253 int chars; 254 long total; 255 char[] buffer; 256 257 buffer = new char[bufferSize]; 258 total = 0; 259 260 try 261 { 262 while ((chars = source.read(buffer)) != -1) 263 { 264 // Technically, some read(char[]) methods may return 0 and we cannot 265 // accept that as an indication of EOF. 266 if (chars == 0) 267 { 268 chars = source.read(); 269 if (chars < 0) 270 break; 271 dest.write(chars); 272 dest.flush(); 273 ++total; 274 if (listener != null) 275 listener.bytesTransferred(total, chars, streamSize); 276 continue; 277 } 278 279 dest.write(buffer, 0, chars); 280 dest.flush(); 281 total += chars; 282 if (listener != null) 283 listener.bytesTransferred(total, chars, streamSize); 284 } 285 } 286 catch (IOException e) 287 { 288 throw new CopyStreamException("IOException caught while copying.", 289 total, e); 290 } 291 292 return total; 293 } 294 295 296 /*** 297 * Copies the contents of a Reader to a Writer using a 298 * copy buffer of a given size. The contents of the Reader are 299 * read until its end is reached, but neither the source nor the 300 * destination are closed. You must do this yourself outside of the 301 * method call. The number of characters read/written is returned. 302 * <p> 303 * @param source The source Reader. 304 * @param dest The destination writer. 305 * @param bufferSize The number of characters to buffer during the copy. 306 * @return The number of characters read/written in the copy operation. 307 * @exception CopyStreamException If an error occurs while reading from the 308 * source or writing to the destination. The CopyStreamException 309 * will contain the number of bytes confirmed to have been 310 * transferred before an 311 * IOException occurred, and it will also contain the IOException 312 * that caused the error. These values can be retrieved with 313 * the CopyStreamException getTotalBytesTransferred() and 314 * getIOException() methods. 315 ***/ 316 public static final long copyReader(Reader source, Writer dest, 317 int bufferSize) 318 throws CopyStreamException 319 { 320 return copyReader(source, dest, bufferSize, 321 CopyStreamEvent.UNKNOWN_STREAM_SIZE, null); 322 } 323 324 325 /*** 326 * Same as <code> copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code> 327 ***/ 328 public static final long copyReader(Reader source, Writer dest) 329 throws CopyStreamException 330 { 331 return copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE); 332 } 333 334 }